initial source drop, apple2-emul-0.7.4.tar.gz

This commit is contained in:
Aaron Culliney 2013-06-11 00:08:15 -07:00
parent 5e4d640afd
commit e71efa3acd
64 changed files with 24098 additions and 0 deletions

11
.apple2 Normal file
View File

@ -0,0 +1,11 @@
speed = 100
mode = ][+ undocumented
disk path = /usr/local/games/apple2/disks
color = interpolated
sound = pc speaker
joystick = pc joystick
joystick range = 256
origin_x = 128
origin_y = 128
sensitivity = 3%
system path = /usr/local/games/apple2/rom

15
ASM Normal file
View File

@ -0,0 +1,15 @@
Begin3
Title: Apple // emulator for Linux
Author: alexb@csd.uu.se (Alexander Jean-Claude Bottema)
sl14@cornell.edu (Stephen Lee)
asc@mhpcc.edu (Aaron Culliney)
michael@talamasca.ocis.net (Michael Deutschmann)
Version: 0.7.4
Entered-date: 2000-03-24
Description: Apple II+, //e emulator. Uses svgalib or X.
Keywords: emulator, linux
Uploader: michael@talamasca.ocis.net (Michael Deutschmann)
Primary-site: ftp.ocis.net /pub/users/ldeutsch/release/
257k apple2-emul-0.7.4.tar.gz
Platform: Linux i386
End

11
AUTHORS Normal file
View File

@ -0,0 +1,11 @@
Alexander Jean-Claude Bottema <alexb@csd.uu.se> made the original
version of the emulator in 1994.
Stephen Lee <sl14@cornell.edu> and particularly Aaron Culliney
<asc@mhpcc.edu> have done much work on the emulator since.
Michael Deutschmann <michael@talamasca.ocis.net> cleaned up the
build sequence to use standard GNU tools, and is the present coordinator.
Tom Lear <tom@trap.mtview.ca.us> maintains the Debian package of
this program, and has contributed some fixes.

339
COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, 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.
GNU GENERAL PUBLIC LICENSE
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.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

1237
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

182
INSTALL Normal file
View File

@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

16
LSM Normal file
View File

@ -0,0 +1,16 @@
Begin4
Title: Apple2/Linux
Version: 0.7.4
Entered-date: 2000-03-24
Description: Apple II+, //e emulator. Uses svgalib or X
Keywords: apple2, emulator
Author: alexb@csd.uu.se (Alexander Jean-Claude Bottema)
sl14@cornell.edu (Stephen Lee)
asc@mhpcc.edu (Aaron Culliney)
Maintained-by: michael@talamasca.ocis.net (Michael Deutschmann)
Primary-site: ftp.ocis.net /pub/users/ldeutsch/release/
257k apple2-emul-0.7.4.tar.gz
Alternate-site: metalab.unc.edu /pub/Linux/system/emulators/
Copying-policy: GPL
Platforms: x86 CPU, either svgalib or X-windows
End

3
Makefile.am Normal file
View File

@ -0,0 +1,3 @@
SUBDIRS = disks src
EXTRA_DIST = README.debugger TODO LSM ASM PROBLEMS .apple2

320
Makefile.in Normal file
View File

@ -0,0 +1,320 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = .
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
DEBUGGER_O = @DEBUGGER_O@
JOYSTICK_O = @JOYSTICK_O@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
PROGS = @PROGS@
VERSION = @VERSION@
SUBDIRS = disks src
EXTRA_DIST = README.debugger TODO LSM ASM PROBLEMS .apple2
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
Makefile.in NEWS TODO acinclude.m4 aclocal.m4 configure configure.in \
install-sh missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in acinclude.m4
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-tags distclean-generic clean-am
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: install-data-recursive uninstall-data-recursive \
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
uninstalldirs-recursive all-recursive check-recursive \
installcheck-recursive info-recursive dvi-recursive \
mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs-am \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

260
NEWS Normal file
View File

@ -0,0 +1,260 @@
Changed in 0.7.4:
Many bugs have been fixed, including a calling-convention mistake that
could cause unpredictable behavior on reboot. Potential buffer overflows
have also been corrected.
Some key assignments have changed. Joystick buttons are now Left-Alt,
Right-Alt & Insert. Delete, formerly a joystick button, now produces the
DEL ascii code. Reboot is now Break (Ctrl-Pause), and Reset is now
Ctrl-Printscreen. (This is reversed from 0.7.3)
Some significant optimizations were also made in the assembly code. The
large memory-access indirection table is now compressed using virtual
memory tricks, to slightly reduce cache load and swap requirements.
Also many cleanups have been made in the internal code. This is
user-invisible, and far from complete. When done, it will become easier to
add new interface cards, video drivers, and other stuff, as well as port
to other unixes.
Changed in 0.7.3:
More makefile/configuration bugs were fixed.
The `Mystery House' sample disk, which was accidently omitted from my
distributions, has been reinstated. Also, I've added a new sample
disk image - William Night's emulator performance tests.
Changed in 0.7.2:
The configure script will now react to absence of X Windows or SVGAlib by
only building an emulator for the remaining graphics system.
A makefile bug that caused xapple-80col not to depend on
all it's source files was fixed. Also, the alternate character set is now
correctly restored on exit from the <F10> menu.
Some major cleanups were done to the assembly-language files. This is
invisible to the user, but should make further enhancement a little saner.
The banners on the source code have been synchronized.
Changed in 0.7.1:
1. Fixed a makefile bug that caused xapple-80col to be miscompiled.
2. Put sample .apple2 (config file) back in. It was accidentally excluded
from 0.7.
3. The SVGA emulator is again named `apple2', not `sapple2'.
Changed in 0.7: (Sep 98)
Version 0.7 - Michael Deutschmann <michael@talamasca.wkpowerlink.com>
1. Replaced "character.rom" and Aaron's MouseText table in misc.c with
a single file, font.txt, which is converted into a packed c table by a
generator utility.
2. Overhauled Makefile system. We now use GNU autoconf/automake.
Note: This hasn't been tested extensively. Also, there are a few automake
tricks I haven't bothered with - I added them to TODO.
Changed is 0.06: (Aug 98)
-------------------------
Version 0.06 - Aaron Culliney <chernabog@baldmountain.bbn.com,
aculline@bbn.com>
My code changes have nothing to do with my employer, GTE
Internetworking, BBN Technologies. They were written completely on my
own time and on my own machine.
1) Separated SVGAlib specific stuff into svideo.c. Added X Windows
frontend support in xvideo.c. The X frontend works by doing an
X(Shm)PutImage() of the emulator's framebuffer around 30 times a
second. This saves us from changing the internal video routines (they
assume direct access to an 8bit framebuffer), and it's a heck of a lot
faster than trying to do an XPutPixels() on each change. The X
frontend only currently works for 8bit displays. Make sure you run it
using a mode (specified in XF86Config) that has a bit depth of 8 (not
16 or greater).
2) We now build three versions of the emulator: svideo_320x200,
xvideo_320x200, xvideo_640x400. The last one really isn't 640x400 for
optimization reasons (568x384) although it probably should be...
Sorry, but there's no support for switching resolutions on the fly, we
ifdef it in with a new define "_640x400".
3) Provided 80column support for the 640x400 X version. Now you
can PR#3 (running as //e) and get 80 columns. This change required
a resolution of at least 560 horizontal pixels (Apple //e specs).
4) Both SVGA and X versions need to be suid root (for PC speaker port
access and SVGA stuff). But both versions now give up root access
during video initialization. This means that disk access is now done
as *you* (not root) even when g(un)zipping images for loading.
Before images would be g(un)zipped as root. There was something about
this that made me uneasy... Now it's up to you to give the
appropriate user/group permissions to your disk image repository.
I make no claim about the security fitness of this emulator. See the
other READMEs and files for more information/disclaimers.
5) Did a 180 on the disk image selection menu. <RET> now tries
to open disk images as read-only, 'W' for both read-write.
Of course this will only work if you have the correct
file permissions set (see 5 above). I find this more convenient b/c
I play alot of the arcade games where you don't ever save game state.
6) Removed the disk "Information" submenu. I never use it. Do you?
Changes in 0.05: (Feb 98)
-------------------------
Version 0.05 - Aaron Culliney <chernabog@baldmountain.bbn.com,
aculline@bbn.com>
My code changes have nothing to do with my employer, GTE
Internetworking, BBN Technologies. They were written completely on my
own time and on my own machine.
1) Added support for 65c02 instructions. The programs that
I've tested which use them work just fine.
2) Added support for 128k //e EXCEPT 80 column mode, B/W
DHIRES mode, and MouseText character set. The two unimplemented video
modes require major changes to current video routines, thus a next
version... New supported images are copy ii+ 9.0, diagnostics //e,
marble madness, airheart, legend of blacksilver, pirates!...
3) Fixed some old problems with HIRES colors being off around
byte edges in interpolated/color modes. but we still give you the
option to use these "lazy" modes since emulation is faster with them
enabled...
4) You now have several new options in your .apple2 file. I
suggest either copying the distributed one over your existing one, or
merging the changes in.
5) Fixed some potential security bugs where a user could
traverse into sensitive directories by using the disk selection
interface. The current emulator version is not guaranteed to be
foolproof since it has to be installed suid root for normal users to
use it. Sysadmins should take extra precautions as they see fit.
6) Added and deprecated some options in the debugger interface
to support the new 128k //e. see the DEBUGGER file for more info.
DEBUGGER support is not default compiled in.
7) added some extra options to the .config file that you build
into the emulator. One big one: a way to set the max delay count in
the emulator to bring Apple ][ emulation rates down to normal on high
end pentiums!... 100 is the default delay rate (which works just fine
for low end 386-Pentium100's).
Changes in 0.04: (June 97)
-----------------------------
Version 0.04 - Aaron Culliney <chernabog@baldmountain.bbn.com,
aculline@bbn.com>
My code changes have nothing to do with my employer, BBN. They were
written completely on my own time and on my own machine.
1) Added PC Joystick Support. You must have the joystick
kernel loadable module 0.8.0 correctly configured and installed to use
this feature.
2) Changed the way the emulator handles the language card
memory space. We no longer patch rom/ram on lc_c08x functions. I did
this because under certain conditions the previous versions of the
emulator would run a lot slower. Now you may notice the emulator
running a tad slower in general (because of the range checking), but
Ultima 4 and Arctic Fox (formerly unplayable) should now be just fine.
3) Changed the way the .apple2 preferences file is handled. I
Did this mainly to support saving of PC Joystick parameters, and I'd
rather let flex do the dirty work of regexp matching.
4) Changed the disk interface and main interface menu. In the
disk interface, you can now see which disk is in the drive, and with
what permission <rw1> for read/write drive 1. You can eject this disk
or force it to be write-protected. In the main menu screen, you have
more parameters to play around with (associated with the pc joystick
add-on).
5) Disk image files are now opened with user privileges, not
root privileges, even though the program is suid root. gzip'ed disks
are still handled as root, but we no longer call the unsecure system()
to do the dirty work. Instead we fork and directly exec "/bin/gzip".
5) General bug fixes and enhancements.
Changes in 0.03: (Jan-Feb 97)
-----------------------------
Version 0.03 - Aaron Culliney <chernabog@baldmountain.bbn.com>
My code changes have nothing to do with my employer, BBN. They were
written completely on my own time and on my own machine.
1) Fixed language card initialization bug.
2) Improved colors. Seems that Greens and purples we're
switched around. The colors are still slightly off, and color
interpolation seems screwy (TODO).
3) Added apple II debugger interface. This requires flex
version 2.5.2. (You can compile this into the program or leave it
out.) Type F7 to get into the debugger and type a '?' to see a
command summary. Check out the file DEBUGGER for more info.
4) Added support for standard 232960 .nib disks.
5) Added a more intuitive interface to selecting disks. You
can now traverse forward and backward in a directory hierarchy with
the base directory set by your .apple2 config file.
6) changed keymap: shift-p = @ and shift-N = ^, just like my
old II+ keyboard.
Changes in 0.02: (8 Dec 1995)
-----------------------------
* Ctrl-C will not kill the emulator with newer SVGAlib. Please
use SVGAlib > 1.2.9 for best results.
* Rudimentory REPT key handling. It's too fast though.
* The assembler files now compiles under ELF.
* Not every SVGA card can do page-flipping. The emulator now
checks for this and fall back to VGA if it can't.
* Keymap has changed a bit. Backspace and ']' is now <-, '[' is
REPT.
* Disk extension changed to the more common .dsk (and a2d.info to
dsk.info).
Changes in 0.01: (9 Oct 1994)
-----------------------------
* Standard VGA support with some performance degradation.
(When page flipping occurs, 64K memory banks are swapped;
hence the performance degradation.)
* -vga flag switch added, e.g. "apple2 -vga"; forces standard
VGA detection.
* (Trident) TVGA8900 page flipping bug fixed.
* File names may now contain any character codes. (The previous
version had some problems with compressing/uncompressing file
names with extraordinary characters.)
* Diskette selection retains last cursor position.

115
PROBLEMS Normal file
View File

@ -0,0 +1,115 @@
Known issues with the emulator:
Emulation Fidelity:
- Disk emulation. The emulator is not very realistic. It handles almost
all non-copyprotected disk access okay, but copyprotected or diagnostic
programs may be confused by our drive, which magically spins at precisely
the optimal speed. (see Specific Programs, below).
- Medium Resolution graphics. This is a rarely used //e mode that is to
Low-Res what 80 Column text is to 40 column text. We don't support it as
yet, although it should be relatively simple.
- Joystick. The apple joystick hardware is read by measuring the time it
takes for a specific softswitch to clear. The emulator cannot as yet
compensate for the speed of the loop used to measure the joystick --
applications using ROM routines will be fine, but custom joystick code
may become mistuned. The Range configuration feature can be used to
compensate for this.
- We don't emulate the //e's vertical blanking interval detection feature.
Graphics:
- Composite graphics artifacts are not emulated. This is not a big
interest to me (Michael), but the previous programmers have suggested it.
- B/W color setting does not apply to lores or double hires. This
generally is not an issue in practice though, as it's really only needed
to avoid color fringing in b/w hires images.
- Double Hires mode is always 140x192 color. Some applications use it as
a 560x192 b/w display however. Note that most applications indicate
which mode they want using the high bit of the dhires data bytes, so it
wouldn't need to be a preferences setting.
- If an 80-column mode is selected in the low-res emulator, nothing will
be written to the display -- the image from the last video mode will
remain on the screen. If a menu is brought up it will `stick'. This may
make people think the emulator crashed, although it will recover if the
application returns to 40-column mode.
- There is no 80-column mode for svgalib apple2. It would be possible on
standard VGA, although there are not enough colors to do flashing letters
by palette tricks as we do now.
- In X, the emulator window takes over the palette, causing all the other
windows to be miscolored. We only need 20 or so colors, so it would be
better if we could share the common palette.
Keyboard:
- Key Handling is a little messy, especially with the way the X support
is bolted on top of core code originally designed for SVGA scancodes.
- Presently, the Backspace key is interpreted as Left-Arrow (Code 0x88).
It could be argued that it should be interpreted as Delete (Code 0xff)
instead. Real Apples had no seperate Backspace key, but the //e's Delete
key was in an analogous position to the PC's Backspace). The PC
keyboard's Delete is assigned to 0xff (in //e mode).
- If you're using Apple ][+ mode, the keyboard may appear broken. That's
a feature -- the program is imitating the historical ][+ keyboard layout.
Press F5 to see a map. Maybe we should add a means to turn it off.
- On my X system, without explict xmodmap or xkbcomp intervention,
Break (reset) won't work with XKB enabled, and PrintScreen (reboot) won't
work with it disabled.
This is X's fault, and I've sent them a bug-report, but maybe we should
consider moving the keys (again...)
Miscellany:
- Older versions of this file note problems with scandir() in the
presence of orphan symlinks in some versions of the C library. Hasn't
been a problem for my glibc 2.1.2 system.
- Presently the programs are not automatically set SUID on install.
- The emulator requires ROMs for both ][+ and //e even if only used to
emulate one of them.
- In theory, typing "Ctrl-Left Alt-Pause" should be equivalent to
"Ctrl-Open Apple-Reset" and make the //e reboot. This doesn't work
properly in practice. Somehow CXROMINT is not cleared at disk-interface
detection time, so the disk won't boot.
(Ctrl-Right Alt-Pause activates diagnostic mode, as expected.)
Specific Programs:
- Some programs (Computist's Nibbler, Sword of Kadash Master copy for
example) lock up. It appears (in debugger) that they are reading the disk
with the motor off. Perhaps they pulsed the real Apple's drive motor to make
it turn slower?
- ProDOS will refuse to format disks, claiming that the disk is too slow.
- ``Alternate Reality: The City'' seems to get jammed, rapidly changing
the video mode. I'm not sure if this is a real failure, or just a special
effect that takes longer than I'm willing to wait to finish (mode switches
would be much faster on a real Apple.) I can get into the program
with some nontrivial debugger manipulation to `short out' the offending loops.
- ``Moon Patrol'' will crash in ][+ mode at the end of the first level
(ie: Point E). This is caused by a "02" opcode at address 1E15, an
undocumented HANG instruction. //e mode works, since the 65C02 treats
this instruction as a no-op.
Moon Patrol may actually be //e-only. Yet this seems a gratutious
incompatibility, since the fact you can play the first level (and further
ones using the debugger) under ][+ mode indicates it doesn't need any //e
features. Perhaps the bug was introduced by the people who cracked it's
copy protection.

408
README Normal file
View File

@ -0,0 +1,408 @@
**************************************************************************
* Apple II+ Emulator version 0.7 for Linux *
* *
* Original Author: Alexander Jean-Claude Bottema *
* Email : d91a1bo@meryl.csd.uu.se *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Modified: Dec 8 1995 by Stephen Lee <sl14@cornell.edu> *
* Modified: Jan 97 by Aaron Culliney <aculline@bbn.com> *
* <chernabog@baldmountain.bbn.com> *
* Modified: Jun 97 by Aaron Culliney <aculline@bbn.com> *
* <chernabog@baldmountain.bbn.com> *
* Modified: Feb 98 by Aaron Culliney <aculline@bbn.com> *
* <chernabog@baldmountain.bbn.com> *
* Modified: Aug 98 by Aaron Culliney <aculline@bbn.com> *
* <chernabog@baldmountain.bbn.com> *
* *
* Modified: Sep 98, Dec 98, Jan 98, Jun 99 *
* by Michael Deutschmann *
* <michael@talamasca.wkpowerlink.com>*
* *
**************************************************************************
NOTE:
This is basically the original README. See the CHANGES file
first for information on this specific version of the emulator. Then
read section 0 (installation) in this file for cookbook compilation /
installation instructions. Other information in this file may be
outdated, so read the manpage for up-to-date runtime instructions.
Contents
========
0. Installation issues (briefly)
1. Why did I make an Apple II+ Emulator when there are so many available?
2. System Files
3. Keyboard & keys
4. Diskette database
5. Future plans
6. Status of the current emulator
7. Can you port this to DOS?
8. Availability
9. Known problems
10. Changes since the last
11. Final words
0. Installation issues (briefly)
================================
Requirements: SVGA lib version 1.2.9 (or later, see 9.) Tested under 1.2.13.
Kernel 2.0.X. Tested under 2.0.36pre12.
libc 4.4.4 (or later). Tested under glibc-2.0.6
joystick 0.8.0 kernel module for PC Joystick support.
flex 2.5.2 (for compiling lex files)
1) Unpack this distribution in a temporary directory.
2) Run "configure" for a normal build, or "configure --enable-debugger"
to add debugger support. (Other GNU autoconf options, such as --prefix,
may of course be used.) You may provide optimizations in the enviroment
variable CFLAGS.
3) Type "make" to make the program. As root, type "make install" to
install the programs in $(BINDIR) and the man page in $(MANDIR), (both
configurable at the configure line). The sysadmin should enable the
setuser bit on "apple2" in order for it to use the VGA. Enabling setuser
on "xapple2" will allow use of the PC speaker, but is not essential.
4) Copy the .apple2 configuration file to your home directory, and
read the manpage that was installed for further information on how to
configure this file. You can configure most of the settings from
within the emulator, (F10 for the menu screen), but you need the
system path correctly set to point to the rom files before you start
the emulator. The emulator won't run without the correct rom files
(see the manpage).
5) After you're done configuring, type "xapple2" to run the
emulator under X or "apple2" to run using svgalib. There are two X11
versions for different resolutions. Once running, F1 selects disk
drive #1, F2 selects disk drive #2, F10 gives you the main menu of
runtime parameters, and F5 shows you the keyboard lay out.
1. Why did I make an Apple II+ Emulator when there are so many available?
=========================================================================
For three reasons. The first is that there are no Apple II emulators
especially written for Linux; hence they do not take advantages that
are commonly provided in Linux systems, e.g. the SVGA library
distribution. However, there is an Apple II emulator for X-Windows
that easily can be compiled on most UN*X architectures, but the major
disadvantage is slow emulation. You cannot obtain a fast emulator by
writing it in C, despite the elegant optimizations provided by GNU-C,
but of course it becomes more portable if you do that.
By contrast, this Apple II emulator is partly written in 386 (AT&T)
assembler; partly in C. Only those issues that were not time critical
were written in C. Especially the CPU emulation was written in
optimized assembler to achieve optimum performance. The emulator
approximately runs twice as fast as an ordinary Apple II+ computer if
it is running on a 486 DX-50.
The second reason is that there is no Apple II emulator which is 100%
usable. Either it is too slow or it is simply too fast (= there is no
option to trim the speed of the emulator). Furthermore, many
implementors happily avoid implementing mixed text/graphics in high
resolution mode; mostly because it complicates the programming. I have
never seen an Apple II+ emulator that is entirely complete. I think
most emulators fail on implementing the undocumented 6502 instructions
(those that are listed as ???), hence some games (or applications) may
not work despite they should.
The third reason is that no emulator support an easy way to switch
diskettes given a database of diskettes. With this emulator you can
easily switch diskettes through an intuitive interface. You can also
add additional information for each diskette (in your database), e.g.
which keys to use for a particular game program. The information is
kept in a plain text file that can be edited with an ordinary text
editor, preferbly GNU-Emacs.
(Aaron removed the above feature)
2. System files
===============
Before you can run the emulator, three vital system files must be
available. These are:
apple_II.rom (12k) This file contains the ROM of your Apple II+.
It is not distributed due to copyright issues.
You have to get this file on your own. If you
have been running another emulator, you can
probably use its ROM files directly. Technically
speaking, this file is a memory dump of the
consecutive addresses from D000 to FFFF. This
file may also be called by other names such as
apple.rom or apple2.rom, but is referenced
internally as apple_II.rom.
appple_IIe.rom Likewise for IIe emulation.
slot6.rom (256 bytes) Memory dump of the consecutive addresses from
C600 to C6FF. This file is not distributed
either due to the same reasons as above. This
file may also be called by other names such as
controller.rom, but is referenced internally
as slot6.rom.
Other important files
---------------------
.apple2 This file is distributed. The file contains default
parameter settings. The most important parameter is
the setting of the system path, i.e. the directory
where the three vital system (ROM) files are
stored. Most of the other parameters can be
changed during run time via the interface
(activated by pressing F10).
Parameters (that can be set in .apple2):
speed = <percentage>% Speed of the emulator
path = <directory> Diskette database directory
color = off Monochrome mode
on Plain color mode
interpolated Interpolated color mode
sound = off Silent mode
pc speaker Sound through PC speaker
joystick = off Joystick disabled
linear Linear joystick mode
pc joystick PC Joystick (see CHANGES)
digital (Atari) digital joystick mode
not yet supported
joystick range 1-256 range of joystick
origin_x = 0-255 Origin of the joystick (X)
origin_y = 0-255 Origin of the joystick (Y)
sensitivity <percentage>% Joystick sensitivity
system_path = <directory> Directory where the system
ROM files are stored.
pc joystick parms You don't want to fool
around with these, you
generate these parms from
F10 screen "Calibrate" menu
item.
dsk.info An example is distributed. This file contains
information for various diskettes kept in the database.
Syntax:
{<Name of diskette>} i.e. the name is written
within curly braces.
<Any information...>
{<Name of another diskette>} ... etc.
3. Keyboard & keys
==================
F1 To switch diskettes in Drive A, Slot 6
F2 To switch diskettes in Drive B, Slot 6
F4, also Pause key Pause
F5 Keyboard layout
F8 Words from the author (removed)
F9 Toggle between maximum speed and configured speed.
F10 General parameter settings
Break (ctrl-Pause) Apple II Reset key
Ctrl Printscreen Reboot Apple II emulator
The numeric keypad is used for joystick emulation.
Left Alt Joystick button 0
Right Alt Joystick button 1
Insert Joystick button 2
F7 Debugger - (if it's compiled into the source).
Edit the Makefile if you don't want the
debugger. The emulator will run slightly
faster without the debugger.
4. Diskette database
====================
The diskettes are provided as plain binary files. These are actually
raw dumps, containing the tracks from 0 to 34. For the standard
143360 byte .dsk format each track is partitioned into sectors
numbered from 0 to 15. Each sector is 256 bytes. Hence, the data is
organized as the following:
File offset (in bytes) Sector Track
---------------------- ------ -----
0 0 0
256 1 0
512 2 0
. . .
. . .
. . .
3840 15 0
4096 0 1
4352 1 1
. . .
. . .
. . .
143104 15 34
To transfer Apple II diskettes into this format requires that you own
an original Apple II. Since the drives provided by the IBM PC's are
not compatible with the original Apple II drives there are no
conversion programs directly available. If you have used other Apple
II emulators it is most likely that the files will work with this
emulator too. It seems to be a common standard to structure the
diskettes in the above described way, e.g. the ApplePC and Apl2em
emulators for DOS uses the same structure.
Emulated diskettes MUST have the .dsk or .nib extension (143360 bytes
or 232960 bytes respectively), otherwise the emulator will not
recognize the file as a valid diskette. However, it is valid to
compress them by using gnu-zip (then the extension becomes .dsk.gz or
.nib.gz). The emulator will automatically decompress/compress them
whenever required (note that it assumes /bin/gzip exists).
Note that you can add information/documentation for the dsk-diskettes
by using an ordinary text editor and edit the file "dsk.info". The
name of the diskette is written in curly braces (without the .dsk
extension) followed by any information.
5. Future plans
===============
I intend to improve the emulator. Actually, for the next major release
(i.e. version 1.00) the emulator will be entirely rewritten. For minor
changes, see file CHANGES.
[Note from Stephen Lee: since this hasn't happened yet, I took to
improving the existing emulator until Alexander release a new one.]
[Note from Aaron Culliney: since this still hasn't happened, I also
took the liberty to fix a few things and add some functionality.]
[v004 note: decided to add in some more features, and fix problems as
they've arisen.]
6. Status of the current emulator
=================================
Works in standard VGA Y
Works in SVGA (then using SVGA facilities) Y
Disk drive emulation (slot 6) (.dsk & .nib) Y
Disk drive emulation (slot 5) N (release 1.00)
High resolution emulation Y
Low resolution emulation Y
Mixed mode (in all resolution modes) Y
Correct color emulation (both Low and Hi-res) Y
Interpolated color emulation Y
Configurable speed Y
Diskette switching Y
Diskette database Y
Interface for parameter settings, etc. Y
Sound emulation (PC speaker) Y
Flashing text Y
Joystick emulation through numeric keypad Y
Virtual console switching Y (only when emu. is paused)
Raw keyboard mode (reading scancodes) Y
Undocumented 6502 instructions Y
Language card (i.e. additonal 16k RAM) Y
Serial card N (maybe release 1.00)
Works on DOS N (AND NEVER WILL)
Apple II Debugger Y
PC Joystick kernel module support Y
7. Can you port this to DOS?
============================
No, for two reasons. The first, and probably the most important, is
that the current emulator use kernel specific issues that are not, and
never will be, available in DOS. Future emulators will be based on the
same principles, so the emulator will never run in DOS. The second
reason is that DOS is a bad operating system. It is a pain in the neck
to write and debug programs in DOS and there is no usable memory
management provided by the kernel (if the DOS "interrupts" can be
called a "kernel" at all).
With this free software I hope that more users will switch to Linux
(which is a great operating system) and I have a dream that one day,
DOS will become a minority.
8. Availability
===============
This distribution is available at ftp.apple.asimov.net, and
tsx-11.mit.edu, and sites mirroring these.
9. Known problems
=================
Problem: SVGAlib version 1.2.8 and below has a bug in
keyboard-handling that makes the '-' key (in the emulator)
unusable.
Solution: Please use SVGAlib version 1.2.9 or above.
Problem: The REPT (repeat) key repeats too fast.
Answer: The current implementation is a kludge by me [Stephen]. I
might fix it later, but again, I might not.
Problem: I can't switch virtual consoles while running the program
under gdb [Aaron].
Answer: Actually you do, it's just that the graphic mode stays valid.
If you have the svgalib utility "textmode", try a "shell
textmode" reset. I haven't played around enough to figure out
how/if you can get back to graphic mode after this.
Problem: Compiling with optimization causes the debugger to choke
[Aaron].
Answer: I'm playing fast and loose with the debugger's assembly hooks.
I think it's something to do with -fomit-frame-pointer. And
since I don't see much speed gain, I'm ignoring the problem
for now.
10. Changes
===========
see file CHANGES
11. Final words
===============
Note that albeit you can switch between digital and linear joystick
emulation, only linear mode is presently supported. I still haven't
figured out how the atari (digital) joystick emulation works, so I'll
save it to the next release (as I said in the previous release :-) )
[PC Joystick mode is just another linear mode. In general linear mode
seems to work fine for most games. If a game seems to be having
trouble with it, change the range from $100 (256) to $80 (128) with
center points at $80 and $40 respectively. Switching around ranges
often seems to do the trick for most games, but I bet I'm not handling
the joystick softswich values correctly. documentation on this is
scant. -Aaron]
I hope you will enjoy this emulator. I do. Many games (that I have
ported) works perfectly, even those that use undocumented 6502
instructions. Suggestions to improvements are welcome. My email
address will be valid at least one more year, i.e. as long as I am a
computer science student at the University of Uppsala in Sweden.
/ Alexander Jean-Claude Bottema (Email: d91a1bo@meryl.csd.uu.se)
Oct. 9 1994 15:44:21

154
README.debugger Normal file
View File

@ -0,0 +1,154 @@
*************************************************************************
* *
* Apple II debugger routines for the Linux-x86 Apple II emulator. *
* by Aaron Culliney - chernabog@baldmountain.bbn.com - (C) 1998 *
* *
* My code changes have nothing to do with my employer, GTE *
* Internetworking, BBN Technologies. They were written completely on my*
* own time and on my own machine. *
* *
*************************************************************************
The debugger console is a mid-size hack onto the main emulator code.
I did it b/c I wanted to fool around with some of my old games while
they were running and to debug the emulator itself.
The code is kinda ugly in some areas, but seems robust enough; (I've
used flex to handle most of the dangerous UI stuff). It runs a bit
slower than when you're in unrestricted emulation mode because it's
doing a lot of switching between C code and asm, copying state, and
checking breakpoints/watchpoints.
KNOWN PROBLEMS:
--------------
When you hit a watchpoint or breakpoint, you have to step over it
before you can use the g{o}, f{inish}, or u{ntil} commands again.
----------------------------------------------------------------------------
Usage:
-----
F7 - enters the debugger. (actually we wait until we've finished with
the current 6502 instruction before we enter the debugger so we're all
synched up if/when we start stepping the machine).
ESC - exits the debugger console.
General Command format:
command {optional part} <mandatory part> (this | that)
----------------------------------------------------------------------------
Disassembling Apple II main memory and language card memory:
d{is} {language card bank} {/bank/}{addrs} {+}{len}
Examples:
"d" - disassemble from current location
"dis +5" - disassemble from current location +5
"dis /01/2000" - (128k (//e) specific)
"dis lc1 d000 5" - disassemble memory +5 at lang card 1 0xd000
Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language
card.
----------------------------------------------------------------------------
Dumping memory:
m{em} {lc1|lc2} {addrs} {+}{len}
a{scii} {lc1|lc2} {addrs} {+}{len}
Examples:
"mem" - dump memory at current location
"m dead" - dump memory at 0xDEAD
"m lc2 2fff 1" - dump memory at lang card 2 0x2FFF +1
"ascii /01/400" - (128k (//e) specific)
Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language
card. Also you need to specify the {addrs} if you're examining lc
memory.
----------------------------------------------------------------------------
Setting memory:
<addrs> {lc1|lc2} : <byteseq>
"4000:deadc0de" - set memory at 0x4000 to 0xDEADC0DE
"50lc2:def" - set memory at lang bank 2 0x50 to 0xDE0F
Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language
card.
----------------------------------------------------------------------------
Displaying machine state (registers, language card, drive, softswitches):
r{egs} - registers
l{ang} - language card settings
dr{ive} - disk drive settings
vm - other virtual machine settings
----------------------------------------------------------------------------
Stepping the machine:
(s{tep} | n{ext}) {len}
f{inish}
u{ntil}
g{o} {addr}
-*step* or *next* 0-255 instructions.
-*finish* current stack-frame (stop at RTS).
-step *until* PC == next instruction (good for finishing loops).
-*go* or jump to {addr} and continue executing until user hits a key.
----------------------------------------------------------------------------
Searching and setting/unsetting memory breakpoints and watchpoints:
sea{rch} {lc1|lc2} <byteseq>
"se deadc0de" - search for 0xDEADC0DE
"search lc2 def" - search lang bank2 (and lang card) for 0xDEF
(b{reak} | w{atch}) {addr}
br{eak} op <byte>
(c{lear} | i{gnore}) {num}
c{lear} op <byte>
sta{tus} - show status of memory watch/breakpoints
op{codes} - show opcodes that we're stopping at
"w c0e9" - watch memory at C0E9
"br" - break at current PC
"br op 20" - break on opcode 20
"clear 1" - clear breakpoint 1
"ig" - ignore all watchpoints
"cl op 20" - clear break on opcode 20
-break or watch addrs. (use in conjunction with g{o})
-clear breakpoints, ignore watchpoints.
-show break and watchpoint status.
Note: breakpoints and watchpoints persist even when you exit the
debugger console. They are only reset if you clear/ignore them or
virtually reboot.
----------------------------------------------------------------------------
Loading and saving state:
bload <file> <addrs>
bsave <file> /<bank>/<addrs> <len>
bload binary 8000 - load file into memory
bsave pic /0/2000 2000 - save memory to file
----------------------------------------------------------------------------
Miscellaneous:
fr{esh} - clear screen of graphics

12
TODO Normal file
View File

@ -0,0 +1,12 @@
Obviously this emulator could use extension. We could do with support
for more disk-image formats, additional interface cards, memory-image
save/restore, and other things.
However, most of these things would require hooking into parts of the code
that are likely going to change radically in later versions of the
emulator, due to badly needed cleanups. Thus, I do not recommend trying
to extend this version alone.
If you want to work on the emulator, contact us first. We can give you alpha
versions of the emulator to work on, and coordinate your efforts with
other contributors.

12
acinclude.m4 Normal file
View File

@ -0,0 +1,12 @@
dnl This was cribbed from GNU libc (notice the symbol choices), but highly
dnl simplified since we can assume linking is working.
dnl A2_ASM_UNDERSCORES
AC_DEFUN(A2_ASM_UNDERSCORES,[
AC_CACHE_CHECK(for _ prefix on C symbol names, a2_cv_asm_underscores,
[AC_TRY_LINK([asm ("_glibc_foobar:");], [glibc_foobar ();],
a2_cv_asm_underscores=yes,
a2_cv_asm_underscores=no)])
if test $a2_cv_asm_underscores = no; then
AC_DEFINE(NO_UNDERSCORES)
fi
])

117
aclocal.m4 vendored Normal file
View File

@ -0,0 +1,117 @@
dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
dnl This was cribbed from GNU libc (notice the symbol choices), but highly
dnl simplified since we can assume linking is working.
dnl A2_ASM_UNDERSCORES
AC_DEFUN(A2_ASM_UNDERSCORES,[
AC_CACHE_CHECK(for _ prefix on C symbol names, a2_cv_asm_underscores,
[AC_TRY_LINK([asm ("_glibc_foobar:");], [glibc_foobar ();],
a2_cv_asm_underscores=yes,
a2_cv_asm_underscores=no)])
if test $a2_cv_asm_underscores = no; then
AC_DEFINE(NO_UNDERSCORES)
fi
])
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])

2608
configure vendored Executable file

File diff suppressed because it is too large Load Diff

35
configure.in Normal file
View File

@ -0,0 +1,35 @@
AC_INIT(src/apple2.h)
AM_INIT_AUTOMAKE(apple2-emul, 0.7.4)
AC_PROG_CC
AC_CHECK_HEADER(linux/joystick.h, [
AC_DEFINE(PC_JOYSTICK)
JOYSTICK_O=joystick.o])
AC_ARG_ENABLE(debugger, [ --enable-debugger Single-step, &c. support],[
AC_DEFINE(DEBUGGER)
DEBUGGER_O="debug.o debugger.o opcodes.o"])
AC_FUNC_MMAP
A2_ASM_UNDERSCORES
AC_PATH_XTRA
if test -z $no_x
then
PROGS="xapple2 xapple2-80col"
fi
AC_CHECK_LIB(vga,vga_init,PROGS="$PROGS apple2")
# unconditionally enabling //e support. No reason to do without it, IMO
AC_DEFINE(APPLE_IIE)
AC_DEFINE(MAX_APPLE_DELAY,1000)
AC_SUBST(JOYSTICK_O)
AC_SUBST(DEBUGGER_O)
AC_SUBST(PROGS)
AC_OUTPUT([Makefile src/Makefile disks/Makefile])

5
disks/Makefile.am Normal file
View File

@ -0,0 +1,5 @@
# we may want to change this to pkgdata_DATA, to automatically install
# the disk images.
EXTRA_DIST = README blank.dsk.gz blank.nib.gz etc.dsk.gz mystery.dsk.gz \
speedtest.dsk.gz speedtest.txt

173
disks/Makefile.in Normal file
View File

@ -0,0 +1,173 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# we may want to change this to pkgdata_DATA, to automatically install
# the disk images.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
DEBUGGER_O = @DEBUGGER_O@
JOYSTICK_O = @JOYSTICK_O@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
PROGS = @PROGS@
VERSION = @VERSION@
EXTRA_DIST = README blank.dsk.gz blank.nib.gz etc.dsk.gz mystery.dsk.gz speedtest.dsk.gz speedtest.txt
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_COMMON = README Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps disks/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = disks
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

22
disks/README Normal file
View File

@ -0,0 +1,22 @@
Sample Disk Images
------ ---- ------
These disk images are merely distributed with the emulator and are not
actually part of it. (ie: not subject to GPL, and not written by us.)
Many more disk images (including ones we'd never include here due to
copyright considerations) may be found on ftp.apple.asimov.net.
blank.dsk.gz -
blank.nib.gz -
Blank DOS3.3-formatted disk images.
etc.dsk.gz -
A disk with miscellaneous programs, and apparently an assembler.
mystery.dsk.gz -
Sierra's old Mystery House game, now freely distributable.
speedtest.dsk.gz -
William Night's emulator benchmarks.

BIN
disks/blank.dsk.gz Normal file

Binary file not shown.

BIN
disks/blank.nib.gz Normal file

Binary file not shown.

BIN
disks/etc.dsk.gz Normal file

Binary file not shown.

BIN
disks/mystery.dsk.gz Normal file

Binary file not shown.

BIN
disks/speedtest.dsk.gz Normal file

Binary file not shown.

74
disks/speedtest.txt Normal file
View File

@ -0,0 +1,74 @@
From: wnight@cafe.net (William Night)
Newsgroups: comp.emulators.apple2
Subject: Speed Test Results
Date: 22 Apr 1995 11:19:31 GMT
Organization: Cafe.Net Internet Access System
Lines: 63
Message-ID: <3naoo3$9q1@scipio.cyberstore.ca>
NNTP-Posting-Host: espresso.cafe.net
X-Newsreader: TIN [version 1.2 PL2]
These are the latest results from SpeedTest 2.2.2
AplWin2 Sim2e Apl2em-2 Applemu
Test
CPU-Index 6.472 3.155 8.532 11.47
TEXT-Index 2.629 0.1957 4.470 6.274
VIDEO-Index 1.388 0.1957 3.990 5.271
DISK-Index 3.297 0.4715 5.690 0.9626
I will post the results from all the tests as soon as I get around to
typing it in. These highlight the actual strengths and weaknesses of
each emulator and are usefull in figuring out how fast an emulator will
run a certain class of programs.
The tests used will remain the same for each minor version level. All
patch-level changes 2.2.x etc will just be to the main program and the
results will be the same as all other patch levels with the same major
and minor versions. For example the results for 2.2.2 and 2.2.8 will be
the same, while the results between 2.2.2 and 2.3.2 are not gauranteed
to be.
These results were obtained on a 486dx4/100 with 4-Dos and QEMM loaded,
the AplWin tests were performed in Windows 3.1 with the appropriate
Win32 extensions added. I have a cirrus logic 5426 1MB VLB card
installed.
My system tests out at 195.7 in Sysinfo from Norton. I don't have any
Video benchmarks that are common enough that the results would mean
anything (see #1 below)
A few comments about the results.
1) Until I get a benchmark program for the machine the emulator is
running on that all people involved can agree on, test results do not mean
anything between platforms or even between two of the same type of machines
running at different speeds. The only way the results should be used is to
compare the relative speeds of two emulators on the same machine.
2) The relative speeds compared to a //e do not mean that the emulator
will perform that quickly or slowly on a video game or other
application, for example, Sim2e appears to be very slow, but plays games
quite well on my machine. The tests are very intensive in a specific
area, where most programs are more general in their use of system
resources.
3) These tests aren't completely fair. The CPU tests are for the most
part, but differences in the way an emulator is implemented make certain
things automatically faster or slower. For instance, both Apl2em-2 and
Applemu use IBM text for the apple text screen, therefore all text
operations are handled by the IBM graphics card, both Sim2e and AplWin2
do their own translation of text to graphics (and achieve a much more
realistic looking screen). With the video tests, Applemu will only do
black-and-white high-res graphics. This gives it an unfair advantage
over the others.
Any suggestions for the next version of speed-test or comments or
questions are welcome.
The new version of SpeedTest will be posted in the next message, and will
probably make it's way onto an FTP site soon.

250
install-sh Executable file
View File

@ -0,0 +1,250 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

188
missing Executable file
View File

@ -0,0 +1,188 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in`
if test -z "$files"; then
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in`
test -z "$files" || files="$files.in"
else
files=`echo "$files" | sed -e 's/:/ /g'`
fi
test -z "$files" && files="config.h.in"
touch $files
;;
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print \
| sed 's/^\(.*\).am$/touch \1.in/' \
| sh
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0

40
mkinstalldirs Executable file
View File

@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

77
src/Makefile.am Normal file
View File

@ -0,0 +1,77 @@
noinst_HEADERS = apple2.h debug.h disk.h interface.h keys.h misc.h \
video.h cpu.h glue.h gluepro.h prefs.h
SUFFIXES = .l-cpp -80.o
man_MANS = apple2.6
EXTRA_PROGRAMS = apple2 xapple2 xapple2-80col
bin_PROGRAMS = @PROGS@
EXTRA_apple2_SOURCES = debugger.c opcodes.c debug.c joystick.c
apple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c \
interface.c misc.c font.c svideo.c compact.c cpu-supp.c \
vidsup.c
apple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ -lvga
apple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@
EXTRA_xapple2_SOURCES = debugger.c opcodes.c debug.c joystick.c
xapple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c \
disk.c interface.c misc.c font.c xvideo.c compact.c \
cpu-supp.c vidsup.c
xapple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ @X_LIBS@ -lX11 -lXext
xapple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@
EXTRA_xapple2_80col_SOURCES = debugger.c opcodes.c debug.c joystick.c
xapple2_80col_SOURCES = cpu.S memory.S glue.S keys.c prefs.c disk.c \
font.c compact.c cpu-supp.c misc.c interface.c
xapple2_80col_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ \
vidsup-80.o xvideo-80.o display-80.o \
@X_LIBS@ -lX11 -lXext
xapple2_80col_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ \
vidsup-80.o xvideo-80.o display-80.o
noinst_PROGRAMS = genfont
BUILT_SOURCES = font.c debug.c glue.S
EXTRA_DIST = font.txt apple2.6 debug.l-cpp genglue
CLEANFILES = font.c debug.c glue.S
# Warning: this will trip on a cross-compile
# (not that we're otherwise portable to non-Linux yet...)
font.c : font.txt genfont
./genfont < $< > $@
glue.S : disk.c misc.c
$(srcdir)/genglue $^ > $@
%-80.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $<
display-80.o: display.S
$(CC) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $<
# I couldn't get Automake's internal Lex support to work with this, as
# Automake assumes the program was built to cope with no -P option. These
# files require it and also need preprocessing.
#
# Of course this is really our fault for being nonportable to standard Lex...
# (which I presume has no -P)
%.c: %.l-cpp
$(CC) -x c -E -P $(CPPFLAGS) $(DEFS) $< | flex -i -P$* -o$@
# Another hack. I can't see any other way to get across to automake that some
# built sources should not be distributed. (since they vary with
# configuration)
dist-hook:
rm -f $(distdir)/font.c $(distdir)/debug.c $(distdir)/glue.S

433
src/Makefile.in Normal file
View File

@ -0,0 +1,433 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
CC = @CC@
DEBUGGER_O = @DEBUGGER_O@
JOYSTICK_O = @JOYSTICK_O@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
PROGS = @PROGS@
VERSION = @VERSION@
noinst_HEADERS = apple2.h debug.h disk.h interface.h keys.h misc.h video.h cpu.h glue.h gluepro.h prefs.h
SUFFIXES = .l-cpp -80.o
man_MANS = apple2.6
EXTRA_PROGRAMS = apple2 xapple2 xapple2-80col
bin_PROGRAMS = @PROGS@
EXTRA_apple2_SOURCES = debugger.c opcodes.c debug.c joystick.c
apple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c interface.c misc.c font.c svideo.c compact.c cpu-supp.c vidsup.c
apple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ -lvga
apple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@
EXTRA_xapple2_SOURCES = debugger.c opcodes.c debug.c joystick.c
xapple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c interface.c misc.c font.c xvideo.c compact.c cpu-supp.c vidsup.c
xapple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ @X_LIBS@ -lX11 -lXext
xapple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@
EXTRA_xapple2_80col_SOURCES = debugger.c opcodes.c debug.c joystick.c
xapple2_80col_SOURCES = cpu.S memory.S glue.S keys.c prefs.c disk.c font.c compact.c cpu-supp.c misc.c interface.c
xapple2_80col_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ vidsup-80.o xvideo-80.o display-80.o @X_LIBS@ -lX11 -lXext
xapple2_80col_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ vidsup-80.o xvideo-80.o display-80.o
noinst_PROGRAMS = genfont
BUILT_SOURCES = font.c debug.c glue.S
EXTRA_DIST = font.txt apple2.6 debug.l-cpp genglue
CLEANFILES = font.c debug.c glue.S
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
X_EXTRA_LIBS = @X_EXTRA_LIBS@
X_PRE_LIBS = @X_PRE_LIBS@
apple2_OBJECTS = cpu.o memory.o display.o glue.o keys.o prefs.o disk.o \
interface.o misc.o font.o svideo.o compact.o cpu-supp.o vidsup.o
apple2_LDFLAGS =
xapple2_OBJECTS = cpu.o memory.o display.o glue.o keys.o prefs.o disk.o \
interface.o misc.o font.o xvideo.o compact.o cpu-supp.o vidsup.o
xapple2_LDFLAGS =
xapple2_80col_OBJECTS = cpu.o memory.o glue.o keys.o prefs.o disk.o \
font.o compact.o cpu-supp.o misc.o interface.o
xapple2_80col_LDFLAGS =
genfont_SOURCES = genfont.c
genfont_OBJECTS = genfont.o
genfont_LDADD = $(LDADD)
genfont_DEPENDENCIES =
genfont_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
man6dir = $(mandir)/man6
MANS = $(man_MANS)
NROFF = nroff
HEADERS = $(noinst_HEADERS)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(apple2_SOURCES) $(EXTRA_apple2_SOURCES) $(xapple2_SOURCES) $(EXTRA_xapple2_SOURCES) $(xapple2_80col_SOURCES) $(EXTRA_xapple2_80col_SOURCES) genfont.c
OBJECTS = $(apple2_OBJECTS) $(xapple2_OBJECTS) $(xapple2_80col_OBJECTS) genfont.o
all: all-redirect
.SUFFIXES:
.SUFFIXES: -80.o .S .c .l-cpp .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
distclean-binPROGRAMS:
maintainer-clean-binPROGRAMS:
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
done
mostlyclean-noinstPROGRAMS:
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
distclean-noinstPROGRAMS:
maintainer-clean-noinstPROGRAMS:
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
apple2: $(apple2_OBJECTS) $(apple2_DEPENDENCIES)
@rm -f apple2
$(LINK) $(apple2_LDFLAGS) $(apple2_OBJECTS) $(apple2_LDADD) $(LIBS)
xapple2: $(xapple2_OBJECTS) $(xapple2_DEPENDENCIES)
@rm -f xapple2
$(LINK) $(xapple2_LDFLAGS) $(xapple2_OBJECTS) $(xapple2_LDADD) $(LIBS)
xapple2-80col: $(xapple2_80col_OBJECTS) $(xapple2_80col_DEPENDENCIES)
@rm -f xapple2-80col
$(LINK) $(xapple2_80col_LDFLAGS) $(xapple2_80col_OBJECTS) $(xapple2_80col_LDADD) $(LIBS)
genfont: $(genfont_OBJECTS) $(genfont_DEPENDENCIES)
@rm -f genfont
$(LINK) $(genfont_LDFLAGS) $(genfont_OBJECTS) $(genfont_LDADD) $(LIBS)
install-man6:
$(mkinstalldirs) $(DESTDIR)$(man6dir)
@list='$(man6_MANS)'; \
l2='$(man_MANS)'; for i in $$l2; do \
case "$$i" in \
*.6*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
else file=$$i; fi; \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst; \
done
uninstall-man6:
@list='$(man6_MANS)'; \
l2='$(man_MANS)'; for i in $$l2; do \
case "$$i" in \
*.6*) list="$$list $$i" ;; \
esac; \
done; \
for i in $$list; do \
ext=`echo $$i | sed -e 's/^.*\\.//'`; \
inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
inst=`echo $$inst | sed '$(transform)'`.$$ext; \
echo " rm -f $(DESTDIR)$(man6dir)/$$inst"; \
rm -f $(DESTDIR)$(man6dir)/$$inst; \
done
install-man: $(MANS)
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-man6
uninstall-man:
@$(NORMAL_UNINSTALL)
$(MAKE) $(AM_MAKEFLAGS) uninstall-man6
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
$(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am: install-binPROGRAMS
install-exec: install-exec-am
install-data-am: install-man
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am: uninstall-binPROGRAMS uninstall-man
uninstall: uninstall-am
all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man6
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-noinstPROGRAMS \
mostlyclean-compile mostlyclean-tags \
mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-binPROGRAMS clean-noinstPROGRAMS clean-compile \
clean-tags clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-binPROGRAMS distclean-noinstPROGRAMS \
distclean-compile distclean-tags distclean-generic \
clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-binPROGRAMS \
maintainer-clean-noinstPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile install-man6 uninstall-man6 install-man \
uninstall-man tags mostlyclean-tags distclean-tags clean-tags \
maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
installcheck-am installcheck install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Warning: this will trip on a cross-compile
# (not that we're otherwise portable to non-Linux yet...)
font.c : font.txt genfont
./genfont < $< > $@
glue.S : disk.c misc.c
$(srcdir)/genglue $^ > $@
%-80.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $<
display-80.o: display.S
$(CC) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $<
# I couldn't get Automake's internal Lex support to work with this, as
# Automake assumes the program was built to cope with no -P option. These
# files require it and also need preprocessing.
#
# Of course this is really our fault for being nonportable to standard Lex...
# (which I presume has no -P)
%.c: %.l-cpp
$(CC) -x c -E -P $(CPPFLAGS) $(DEFS) $< | flex -i -P$* -o$@
# Another hack. I can't see any other way to get across to automake that some
# built sources should not be distributed. (since they vary with
# configuration)
dist-hook:
rm -f $(distdir)/font.c $(distdir)/debug.c $(distdir)/glue.S
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

301
src/apple2.6 Normal file
View File

@ -0,0 +1,301 @@
.\" Apple ][ emulator manpage
.\" by Aaron Culliney - chernabog@baldmountain.bbn.com - (C) 1997-1998
.\"
.\" apple2.6 - manpage which mostly echos README
.\"
.\" $Id: apple2.6,v 1.8 1998/08/25 03:00:00 chernabog Exp $
.\"
.\" MODIFICATION HISTORY
.\" v0.5 by Aaron Culliney <chernabog@baldmountain.bbn.com>, Feb 1998.
.\" v0.6 by Aaron Culliney <chernabog@baldmountain.bbn.com>, Aug 1998.
.\" This code has nothing to do with my employer, GTE Internetworking,
.\" BBN Technologies. It was written completely on my own time and on
.\" my own machine.
.\"
.TH APPLE2 6 "31 August 1998"
.UC 7
.SH NAME
apple2, xapple2 \- Apple ][+ and //e emulator
.SH SYNOPSIS
.ft B
apple2
.PP
.ft B
xapple2 [ -noshm ]
.ft R
.SH DESCRIPTION
.I apple2
(svgalib) and
.I xapple2
(X11) both emulate a 64k Apple ][+ and 128k Apple //e computer (the latter
only if //e support
compiled in). To use the emulator you need to acquire the original
][+ and //e ROM files which are not distributed due to copyright
reasons. The emulator reads standard 143360-byte and 232960-byte disk
image files with
.I .dsk
and
.I .nib
suffixes respectively.
You can also change any images with the extension
.I .do
to
.I .dsk
and they will work too.
.PP
There are only a few command line options:
.TP
.I -noshm
This forces the X11 version to not use the MITSHM extension. This may degrade
the speed of the emulator but allow you to run it remote.
.PP
.ft R
.SH THE .apple2 FILE
The emulator reads user preferences from a
.I .apple2
file located in your home directory. Copy the
.I .apple2
file that comes distributed with the emulator to your home directory.
You can edit the settings using your favorite editor, but most of the
settings can be tweaked from within the emulator (see menus section below).
.TP
.I speed
Speed of emulation, 1 - XXX. (Actually this is an inverse delay-loop counter). 1 is
slow, and XXX is as fast as can be.
A delay loop is needed to bring the emulation rate down to near what would be
considered a normal Apple ][ speed.
The max speed value should be determined by
.I YOU
when you compile the emulator.
For <= 100Mhz Pentium systems, I personally
like a max value of 100 with a normal apple ][ speed somewhere in the 70s.
For faster machines, try larger ranges.
.TP
.I mode
Starting emulation mode. One of "][+", "][+ undocumented", "//e". You can
also dynamically change the emulation mode from within the emulator.
.TP
.I disk path
Toplevel path of disk images directory. Personally I like
/usr/local/games/apple2/disks.
.TP
.I color
Black/white, lazy color, color, lazy interpolated, interpolated.
.TP
.I sound
Off, pc speaker.
.TP
.I joystick
Off, linear, pc joystick.
.TP
.I joystick range
2 - 256. Range of the joystick values. Good settings are 256 and
sometimes 128, with centers at 128 and 64 respectively. This often depends on
the game.
.TP
.I origin_x
X coordinate origin. 128 is good for many games with a range of 256. Others
like 64 with a range of 128.
.TP
.I origin_y
Y coordinate origin. 128 is good for many games with a range of 256. Others
like 64 with a range of 128.
.TP
.I pc joystick parms
You can configure this from within the emulator. Select the 'Calibrate'
option from the F10 menu. If the emulator complains that
it cannot open the joystick device, make sure the module is loaded.
.I This option is only valid if you've compiled the emulator with -DPC_JOYSTICK.
.TP
.I sensitivity
1% - 100%. This value is used for the emulated joystick using the
numeric keypad.
.TP
.I system path
The directory holding the rom files. The emulator won't run if this
is not set properly. You can only change this by editing the
.I .apple2
file.
.PP
So here is an example .apple2 file:
.nf
speed = 72
mode = ][+
disk path = /usr/local/games/apple2/disks
color = interpolated
sound = pc speaker
joystick = pc joystick
joystick range = 256
origin_x = 128
origin_y = 128
pc joystick parms = 767 693 1344 28 1454 28 13
sensitivity = 13%
system path = /usr/local/games/apple2/rom
.fi
.PP
.ft R
.SH ROM FILES
The emulator requires several ROM files to run.
.TP
.I apple_II.rom
You need this file for basic ][+ emulation. It contains the 12K ROM
of your Apple ][+. It is not distributed due to copyright issues, so
you have to get this file on your own. If you have been running
another apple2 emulator, you can most likely use its ROM files
directly. This file is a memory dump of the consecutive addresses
from D000 to FFFF of the Apple ][+. This file may also be named
.I apple.rom
or
.I apple2.rom,
but is referenced internally as
.I apple_II.rom.
.TP
.I slot6.rom
You need this file for basic disk drive emulation. It is 256 byte
memory dump of the consecutive addresses from C600 to C6FF. This file
is not distributed again due to copyright issues. This file may also
be named
.I controller.rom,
but is referenced internally as
.I slot6.rom.
.TP
.I apple_IIe.rom
If //e support was not compiled into the emulator, then you do not need this
file.
It is the 32K ROM of your 128k Apple //e, a dump of main memory (bank 0)
addresses C000-FFFF concatenated with auxiliary memory (bank 1)
addresses C000-FFFF. Because the
.I apple_IIe.rom
contains the C600 slot, you can construct the
.I slot6.rom
file from this one. The
.I apple_IIe.rom
file may also be named
.I apple2e.rom
but is referenced internally as
.I apple_IIe.rom.
.TP
.I character.rom
A 2048 byte ][+ character rom file. This file is distributed with the
emulator.
.PP
.ft R
.SH DISK IMAGES
The emulator reads standard DOS3.3-order 143360 byte '.dsk' images and
raw-nibble 232960 byte '.nib' images. The emulator can handle images
which are gzip'ed as long as the suffixes are '.dsk.gz' and '.nib.gz'
respectively. The emulator simply assumes that /bin/gzip is available
to compress/decompress these images in place as needed and that you have
permission to do so.
.PP
The images are raw binary dumps, containing the tracks from 0 to 34
from the original 5.25 disk. For the standard 143360 byte '.dsk'
format each track is partitioned into sectors of 256 bytes, numbered
from 0 to 15.
.PP
The raw nibblized 232960-byte images are usually made of
programs that have non-standard formatting as a means of copy
protection. The nibblized format attempts to preserve the
non-standard format, and so defeats the copy protection without
"cracking" the program.
.PP
To transfer Apple ][ diskettes into one of these formats requires that
you own an original Apple ][. Since the drives provided by the IBM
PC's are not compatible with the original Apple ][ drives there are no
conversion programs directly available. If you have used other Apple
][ emulators it is most likely that the files will work with this
emulator too. For more information on Apple ][ disk formats and such,
see
.I Beneath Apple DOS
by Don Worth and Pieter Lechner, published long ago by Quality Software.
.PP
.ft R
.SH EMULATOR KEYS/MENUS
.TP
.I F1
Interface to switch disk in Drive A, Slot 6. Arrow keys navigate the
selection. If the disk highlighted is already in the drive, it will
have a <rw1> or <r1> tag after the name indicating read/write or
read-only access. Select this disk to eject it. To select a disk,
you can press 'w' or RETURN to insert it into the drive. Pressing 'w'
will attempt to open the disk as read/write (if you have permission to
do so).
Pressing RETURN defaults to opening the disk read-only. Press
ESC to accept current settings and exit the menu.
.TP
.I F2
Interface to switch disk in Drive B, Slot 6. Same controls as for
.I F1.
.TP
.I F4
Pause the emulation. The Pause/Break key will also work. Hit a key
to resume.
.TP
.I F5
Display the Apple ][+ or //e keyboard layout.
.TP
.I F7
Enter the Debugger console (if this support was compiled into the
program). See the file DEBUGGER that came with the emulator for
command information.
.TP
.I F9
Toggles between maximum speed and configured speed. This is useful to 'fastboot'
programs, and then slip back to normal Apple ][ speed.
.TP
.I F10
General parameter settings menu, including the all-important QUIT option.
You can edit most of the parameters in your
.I .apple2
file from this menu.
Two options worth mentioning are
the 'Calibrate' and 'JS Sample' options. 'Calibrate' lets you
calibrate the PC Joystick device. 'JS Sample' lets you set the sample
rate of the PC Joystick device. 'Save' lets you save the settings to
your
.I .apple2
file.
.TP
.I Special Keys
The key combination Ctrl-'PrintScrn/SysReq' will reboot the machine.
The Ctrl-'Pause/Break' combination will reset the machine. Remember
that 'Pause/Break' alone will pause emulation. AltLeft and AltRight
keys correspond to the OpenApple and ClosedApple keys (joystick
buttons 0 & 1). NOTE: In //e mode try Ctrl-AltRight-'Pause/Break'
sequence for a system self-test. The numeric keypad is used for
emulated joystick movement.
.ft R
.SH BUGS AND STUFF
See the PROBLEMS file that came with the code.
.PP
Using the joystick for some disk images is problematic.
Apparently there is a bug in Apple ]['s where reading values from the
joystick ports too quickly results in a smaller value than normal.
Unfortunately the emulator doesn't emulate this bug in the machine,
but you can mostly get the same
effect by changing the range of the joystick. For instance, games like Space
Rogue and Airheart like a range of 0x80 with the center around 0x40. Most
other games will like a range of 0x100 with the center around 0x80.
.PP
Under X, you may notice that some keys are not working as advertised
(Pause/Break as reboot for instance). Make sure that these keys are mapped.
(Run xmodmap -pke for the current mapping).
.ft R
.SH MORE INFO
More information is available in the online newsgroups
.I comp.emulators.apple2,
and
.I comp.sys.apple2.
.PP
See also:
.TP
.I Apple //e Technical Reference Manual
.TP
.I Beneath Apple DOS
.TP
.I Beneath Apple ProDOS
.ft R
.SH AUTHORS
Apple //e support and revisions v006, v005, v004, v003 by Aaron Culliney
(aculline@bbn.com). Revision v002 by Stephen Lee. Original version(s)
by Alexander Jean-Claude Bottema.

38
src/apple2.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Apple // emulator for Linux: Common definitions
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_H
#define A2_H
#define BANK2 0x10000
/* Code alignment */
#if defined(__i486__) || defined(__i586__)
#define ALIGN .balign 16
#else /* !(__i486__ || __i586__) */
#define ALIGN .balign 4
#endif /* !(__i486__ || __i586__) */
/* Symbol naming issues */
#ifdef NO_UNDERSCORES
#define SN(foo) foo
#define E(foo) .globl foo ; ALIGN ; foo##:
#else /* !NO_UNDERSCORES */
#define SN(foo) _##foo
#define E(foo) .globl _##foo ; ALIGN ; _##foo##:
#endif /* !NO_UNDERSCORES */
#endif/* A2_H */

174
src/compact.c Normal file
View File

@ -0,0 +1,174 @@
/*
* Apple // emulator for Linux: Memory optimizer
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "misc.h"
#include "cpu.h"
/* This code is not essential to emulator operation. It (ab)uses the
* virtual-memory system so that repetitive parts of the memory-access
* indirection table are compressed. This should hopefully relieve load
* on the processor's cache and boost speed.
*
* This file is far more complicated than it needs to be. For the present
* purpose --- emulating an Apple // series machine on an 386 box --- I
* could have hard-wired the compaction specifically for the Apple layout and
* i386 page size.
*
* But it's more flexible - it needs no change to be used in an emulator
* for Nintendo, C64, etc. Support for host processors with different
* page sizes will just be matter of changing the PSIZE and TPAGES macros.
*
*/
#define TSIZE 524288 /* Size of the entire table */
#define PSIZE 4096 /* Size of a page */
#define TPAGES 128 /* pages in table */
#ifndef HAVE_MMAP
void precompact(void){}
void compact(void){}
#else /* HAVE_MMAP */
static int compaction_file = -1;
void pre_compact(void)
{
const char *tmpdir;
char *filename;
char *x;
/* Destroy any old mapping file */
close(compaction_file);
/* Reset the mapping on the table to normal, in case compaction has
* been done before. This also tests if the kernel is advanced enough
* to support this stunt.
*/
x = mmap((void *) cpu65_vmem,
TSIZE,
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE,
0,
0);
if (x == MAP_FAILED)
{
/* mmap failed.
* For now we assume this is because we are running on a system
* which doesn't support cookie-cutter mmap operations.
*
* We set compaction_file to -1 and return. This tells compact to
* do nothing. (The emu still works.)
*/
printf("System does not appear to support fancy mmap\n"
"(error: %m)\n");
compaction_file = -1;
return;
}
/* Create a fresh new mapping file */
tmpdir = getenv("TMPDIR");
if (!tmpdir) tmpdir = "/tmp";
filename = alloca(strlen(tmpdir) + 9);
strcpy(filename,tmpdir);
strcat(filename,"/a2-XXXXXX");
compaction_file = mkstemp(filename);
if (!compaction_file)
{
fprintf(stderr,"cannot open temporary file (%m)\n");
exit(EXIT_FAILURE);
};
unlink(filename);
ftruncate(compaction_file,TSIZE); /* might not be 100% portable */
/* If the ftruncate doesn't work (Single Unix does not require it
* to work for the extending case), try this instead:
*
* lseek(compaction_file,TSIZE-1,SEEK_SET);
* write(compaction_file,"",1);
*/
}
void compact(void)
{
int i,j,n;
char *work;
char *x;
/* Give up if the first mmap didn't work out */
if (compaction_file == -1) return;
work = mmap(0,
TSIZE,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED,
compaction_file,
0);
if (work == MAP_FAILED)
{
fprintf(stderr,"mmap failure (%m)");
exit(EXIT_FAILURE);
}
n = 0;
i = TPAGES;
while (i--)
{
j = n;
while (j-- && memcmp(work+j*PSIZE,
((void *) cpu65_vmem)+i*PSIZE,
PSIZE));
if (j == -1)
{
memcpy(work+n*PSIZE,
((void *) cpu65_vmem)+i*PSIZE,
PSIZE);
j = n++;
}
x = mmap(((void *) cpu65_vmem)+i*PSIZE,
PSIZE,
PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_FILE|MAP_SHARED,
compaction_file,
j*PSIZE);
if (work == MAP_FAILED)
{
fprintf(stderr,"mmap failure (%m)");
exit(EXIT_FAILURE);
}
}
munmap(work,TSIZE);
}
#endif /* HAVE_MMAP */

88
src/cpu-supp.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Apple // emulator for Linux: C support for 6502 on i386
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <string.h>
#include "cpu.h"
/* different than in defs.h! */
#define C_Flag_6502 0x1
#define X_Flag_6502 0x20
#define I_Flag_6502 0x4
#define V_Flag_6502 0x40
#define B_Flag_6502 0x10
#define D_Flag_6502 0x8
#define Z_Flag_6502 0x2
#define N_Flag_6502 0x80
static void initialize_code_tables(void)
{
int i;
for (i = 0; i < 256; i++)
{
unsigned char val = 0;
if (i & C_Flag)
val |= C_Flag_6502;
if (i & X_Flag)
val |= X_Flag_6502;
if (i & I_Flag)
val |= I_Flag_6502;
if (i & V_Flag)
val |= V_Flag_6502;
if (i & B_Flag)
val |= B_Flag_6502;
if (i & D_Flag)
val |= D_Flag_6502;
if (i & Z_Flag)
val |= Z_Flag_6502;
if (i & N_Flag)
val |= N_Flag_6502;
cpu65_flags_encode[ i ] = val | 0x20;
cpu65_flags_decode[ val ] = i;
}
}
void cpu65_set(int flags)
{
initialize_code_tables();
switch (flags & 0xf)
{
case CPU65_NMOS:
if (flags & CPU65_FAULT)
memcpy(cpu65__opcodes,cpu65__nmosbrk,1024);
else
memcpy(cpu65__opcodes,cpu65__nmos,1024);
break;
case CPU65_C02:
memcpy(cpu65__opcodes,cpu65__cmos,1024);
break;
default:
abort();
}
cpu65__signal = 0;
}
void cpu65_interrupt(int reason)
{
cpu65__signal = reason;
}

3348
src/cpu.S Normal file

File diff suppressed because it is too large Load Diff

131
src/cpu.h Normal file
View File

@ -0,0 +1,131 @@
/*
* Apple // emulator for Linux: Virtual 6502/65C02 interface
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef __ASSEMBLER__
#include <sys/types.h>
/* types */
typedef void *WMEM;
typedef void *RMEM;
struct memory_vector
{
RMEM r;
WMEM w;
};
struct cpu65_state
{
u_int16_t pc; /* Program counter */
u_int8_t a; /* Accumulator */
u_int8_t f; /* Flags (order not same as in real 6502) */
u_int8_t x,y; /* Index register */
u_int8_t sp; /* Stack Pointer */
};
struct cpu65_extra /* for debugging */
{
u_int16_t ea; /* Last effective address */
u_int8_t d; /* Last data byte written */
u_int8_t op; /* 1 = read occured, 2 = write, 3 = both */
};
/* 6502 CPU models */
#define CPU65_NMOS 0x0
#define CPU65_C02 0x1
#define CPU65_FAULT 0x100 /* Undoc. opcodes are BRK */
#define CPU65_SYNCHRO 0x200 /* Synchronize speed, not imp. */
/* Set up the processor for a new run. Sets up opcode table.
*/
extern void cpu65_set(int flags);
/* Interrupt the processor */
extern void cpu65_interrupt(int reason);
extern void cpu65_run(void);
extern void cpu65_step(void);
extern void cpu65_direct_write(int ea,int data);
extern struct memory_vector cpu65_vmem[65536];
extern struct cpu65_state cpu65_current;
extern struct cpu65_extra cpu65_debug;
extern unsigned char cpu65_flags_encode[256];
extern unsigned char cpu65_flags_decode[256];
extern unsigned int cpu65_delay;
#endif /* !__ASSEMBLER__ */
#define RebootSig 0x01
#define ResetSig 0x02
#define DebugStepSig 0x04
#define EnterDebugSig 0x08
/* Note: These are *not* the bit positions used for the flags in the P
* register of a real 6502. Rather, they have been distorted so that C,
* N and Z match the analogous flags in the _80386_ flags register.
*
* Additionally, V matches the position of the overflow flag in the high byte
* of the 80386 register.
*
*/
#define C_Flag 0x1 /* 6502 Carry */
#define X_Flag 0x2 /* 6502 Xtra */
#define I_Flag 0x4 /* 6502 Interrupt disable */
#define V_Flag 0x8 /* 6502 Overflow */
#define B_Flag 0x10 /* 6502 Break */
#define D_Flag 0x20 /* 6502 Decimal mode */
#define Z_Flag 0x40 /* 6502 Zero */
#define N_Flag 0x80 /* 6502 Neg */
#define C_Flag_Bit 8 /* 6502 Carry */
#define X_Flag_Bit 9 /* 6502 Xtra */
#define I_Flag_Bit 10 /* 6502 Interrupt disable */
#define V_Flag_Bit 11 /* 6502 Overflow */
#define B_Flag_Bit 12 /* 6502 Break */
#define D_Flag_Bit 13 /* 6502 Decimal mode */
#define Z_Flag_Bit 14 /* 6502 Zero */
#define N_Flag_Bit 15 /* 6502 Neg */
#define X_Reg %bl /* 6502 X register in %bl */
#define Y_Reg %bh /* 6502 Y register in %bh */
#define A_Reg %cl /* 6502 A register in %cl */
#define F_Reg %ch /* 6502 flags in %ch */
#define FF_Reg %ecx /* 6502 flags for bt */
#define SP_Reg %edx /* 6502 Stack pointer */
#define SP_Reg_L %dl /* 6502 Stack pointer low */
#define SP_Reg_H %dh /* 6502 Stack pointer high */
#define PC_Reg %si /* 6502 Program Counter */
#define PC_Reg_E %esi /* 6502 Program Counter */
#define EffectiveAddr %di /* Effective address */
#define EffectiveAddr_E %edi /* Effective address */
#ifndef __ASSEMBLER__
/* Private data. */
extern void *cpu65__opcodes[256];
extern void *const cpu65__nmos[256];
extern void *const cpu65__nmosbrk[256];
extern void *const cpu65__cmos[256];
extern unsigned char cpu65__signal;
#endif /* !__ASSEMBLER__ */

104
src/debug.h Normal file
View File

@ -0,0 +1,104 @@
/*
* Apple // emulator for Linux: Definitions for debugger
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_DEBUG_H
#define A2_DEBUG_H
#include <stdio.h>
/* debugger defines */
#define BUF_X 39
#define BUF_Y 22
#define MAX_BRKPTS 16
#define SCREEN_X 41
#define SCREEN_Y 24
#define PROMPT_X 2
#define PROMPT_Y BUF_Y - 1
#define PROMPT_END_X BUF_X - 2
#define command_line command_buf[PROMPT_Y]
#define uchar unsigned char
/* debugger commands */
enum token_type { MEM, DIS, REGS, SETMEM, STEP, FINISH, UNTIL, GO, VM,
BREAK, WATCH, CLEAR, IGNORE, STATUS, OPCODES, LC, DRIVE,
SEARCH, HELP, LOG, BSAVE, BLOAD, SAVE, UNKNOWN };
enum addressing_mode
{
addr_implied,
addr_accumulator,
addr_immediate,
addr_zeropage,
addr_zeropage_x,
addr_zeropage_y,
addr_absolute,
addr_absolute_x,
addr_absolute_y,
addr_indirect,
addr_indirect_x,
addr_indirect_y,
addr_j_indirect, /* non-zeropage indirects, used in JMP only */
addr_j_indirect_x,
addr_relative
};
struct opcode_struct
{
const char *mnemonic;
enum addressing_mode mode;
};
extern const struct opcode_struct *opcodes;
extern int step_next; /* stepping over instructions */
extern char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */
extern int num_buffer_lines; /* num lines of output */
extern int arg1, arg2, arg3; /* command arguments */
extern int breakpoints[MAX_BRKPTS]; /* memory breakpoints */
extern int watchpoints[MAX_BRKPTS]; /* memory watchpoints */
void clear_debugger_screen();
void bload(FILE*, char*, int);
void show_misc_info();
unsigned char get_current_opcode();
void dump_mem(int, int, int, int, int);
void search_mem(char*, int, int);
void set_mem(int, char*);
void set_lc_mem(int, int, char*);
void disasm(int, int, int, int);
void clear_halt(int*, int);
void set_halt(int*, int);
void show_breakpts();
void show_regs();
void display_help();
void show_lc_info();
void show_disk_info();
void c_do_step(int);
int at_haltpt();
void end_step();
void set_halt_opcode(unsigned char opcode);
void set_halt_65c02();
void clear_halt_65c02();
void clear_halt_opcode(unsigned char opcode);
void show_opcode_breakpts();
extern const struct opcode_struct opcodes_6502[256];
extern const struct opcode_struct opcodes_65c02[256];
extern const struct opcode_struct opcodes_undoc[256];
extern const char * const disasm_templates[15];
#endif

901
src/debug.l-cpp Normal file
View File

@ -0,0 +1,901 @@
/*
* Apple // emulator for Linux: Lexer for debugger
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
/* ASSUMPTIONS:
* flex version 2.5.2 or later
*
* this file is processed in several steps. the Makefile first
* runs it through cpp so that we can eliminate whole rules which
* are unnecessary. the generated file is then run through flex
* to generate the actual c code which is then compiled.
*
*/
%{
/* process includes only the second time we parse this file. */
#define INC(HASH,STR) HASH ## include STR
INC(#,"misc.h")
INC(#,"interface.h")
INC(#,"debug.h")
INC(#,"disk.h")
INC(#,"video.h")
INC(#,"keys.h")
INC(#,<unistd.h>)
INC(#,<strings.h>)
INC(#,<ctype.h>)
INC(#,"cpu.h")
YY_BUFFER_STATE buffer = 0;
/*
d{is} {lc1|lc2} {/bank/}{addr} {+}{len}
m{em} {lc1|lc2} {/bank/}{addr} {+}{len}
a{scii} {lc1|lc2} {/bank/}{addr} {+}{len}
r{egs}
<addr> {lc1|lc2} : <byteseq>
bload <file> <addrs>
bsave <file> /<bank>/<addrs> <len>
(s{tep} | n{ext}) {len}
f{inish}
u{ntil}
g{o} {addr}
sea{rch} {lc1|lc2} <bytes>
(b{reak} | w{atch}) {addr}
(b{reak} | w{atch}) {addr}
b{reak} op <byte>
(c{lear} | i{gnore}) {num}
c{lear} op <byte>
key <byte>
sta{tus}
l{ang}
dr{ive}
vm
fr{esh}
(? | h{elp})
*/
%}
DEC [0-9]
HEX [0-9a-fA-F]
WS [\n\r\t" "]
CHAR [^\n\r\t" "]
BOS ^
EOS {WS}*\0
BANK \/0?[01]\/
ADDRS [0-9a-fA-F]+
%%
{BOS}(me?m?|as?c?i?i?){WS}+{ADDRS}{WS}\+?+{HEX}+{EOS} {
/* mem <addrs> <len> */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, arg2, 0, do_ascii, -1);
return MEM;
}
#ifdef APPLE_IIE
{BOS}(me?m?|as?c?i?i?){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* mem /<bank>/<addrs> <len> */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, arg2, 0, do_ascii, arg3);
return MEM;
}
#endif
{BOS}(me?m?|as?c?i?i?){WS}+{ADDRS}{EOS} {
/* mem <addrs> */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, 256, 0, do_ascii, -1);
return MEM;
}
#ifdef APPLE_IIE
{BOS}(me?m?|as?c?i?i?){WS}+{BANK}{ADDRS}{EOS} {
/* mem /<bank>/<addrs> */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, 256, 0, do_ascii, arg3);
return MEM;
}
#endif
{BOS}(me?m?|as?c?i?i?){WS}+\+{HEX}+{EOS} {
/* mem +<len> */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (*debugtext != '+') ++debugtext;
++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
dump_mem(cpu65_current.pc, arg1, 0, do_ascii, -1);
return MEM;
}
{BOS}(me?m?|as?c?i?i?){EOS} {
/* dump mem from current location */
int do_ascii = 0;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
dump_mem(cpu65_current.pc, 256, 0, do_ascii, -1);
return MEM;
}
{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* dump mem from lc<bank> <addrs> <len> */
int do_ascii = 0;
int lc;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, arg2, lc, do_ascii, -1);
return MEM;
}
#ifdef APPLE_IIE
{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* dump mem from lc<bank> /<bank>/<addrs> <len> */
int do_ascii = 0;
int lc;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, arg2, lc, do_ascii, arg3);
return MEM;
}
#endif
{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{ADDRS}{EOS} {
/* dump mem from lc<bank> <addrs> */
int do_ascii = 0;
int lc;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
arg1 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, 256, lc, do_ascii, -1);
return MEM;
}
#ifdef APPLE_IIE
{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{EOS} {
/* dump mem from lc<bank> /<bank>/<addrs> */
int do_ascii = 0;
int lc;
if (tolower(debugtext[0]) == 'a')
do_ascii = 1;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
dump_mem(arg1, 256, lc, do_ascii, arg3);
return MEM;
}
#endif
{BOS}di?s?{WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* disassemble at <addrs> <len> */
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
disasm(arg1, arg2, 0, -1);
return DIS;
}
#ifdef APPLE_IIE
{BOS}di?s?{WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* disassemble at /<bank>/<addrs> <len> */
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
disasm(arg1, arg2, 0, arg3);
return DIS;
}
#endif
{BOS}di?s?{WS}+{ADDRS}{EOS} {
/* disassemble at <addrs> */
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_current.pc;
disasm(arg1, arg2, 0, -1);
return DIS;
}
#ifdef APPLE_IIE
{BOS}di?s?{WS}+{BANK}{ADDRS}{EOS} {
/* disassemble at /<bank>/<addrs> */
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = 256;
if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_current.pc;
disasm(arg1, arg2, 0, arg3);
return DIS;
}
#endif
{BOS}di?s?{WS}+\+{HEX}+{EOS} {
/* disassemble current location +<len> */
while (*debugtext != '+') ++debugtext;
++debugtext;
arg1 = strtol(debugtext, &debugtext, 16);
disasm(cpu65_current.pc, arg1, 0, -1);
return DIS;
}
{BOS}di?s?{EOS} {
/* disassemble current location */
disasm(cpu65_current.pc, 256, 0, -1);
return DIS;
}
{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* disassemble language<bank> <addr> <len> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
disasm(arg1, arg2, lc, -1);
return DIS;
}
#ifdef APPLE_IIE
{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} {
/* disassemble language<bank> /<bank>/<addr> <len> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
arg2 = strtol(debugtext, &debugtext, 16);
disasm(arg1, arg2, lc, arg3);
return DIS;
}
#endif
{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{ADDRS}{EOS} {
/* disassemble language<bank> <addr> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
arg1 = strtol(debugtext, &debugtext, 16);
disasm(arg1, 256, lc, -1);
return DIS;
}
#ifdef APPLE_IIE
{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{EOS} {
/* disassemble language<bank> /<bank>/<addr> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
arg1 = strtol(debugtext, &debugtext, 16);
disasm(arg1, 256, lc, arg3);
return DIS;
}
#endif
{BOS}re?g?s?{EOS} {
/* show cpu state */
show_regs();
return REGS;
}
{BOS}{ADDRS}{WS}*\:{WS}*{HEX}+{EOS} {
/* set memory <addr> : <hex string> */
arg1 = strtol(debugtext, &debugtext, 16);
while (*debugtext != ':') ++debugtext; ++debugtext;
while (isspace(*debugtext)) ++debugtext;
set_mem(arg1, debugtext);
return SETMEM;
}
{BOS}{ADDRS}{WS}*(lc1|lc2)\:{WS}*{HEX}+{EOS} {
/* set LC memory <addr> lc1|lc2 : <hex string> */
int lc;
arg1 = strtol(debugtext, &debugtext, 16);
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
++debugtext; while (isspace(*debugtext)) ++debugtext;
set_lc_mem(arg1, lc, debugtext);
return SETMEM;
}
{BOS}bload{WS}+{CHAR}+{WS}+{ADDRS}{EOS} {
/* bload <file> <addr> */
FILE *fp = NULL;
char *ptr = NULL;
char name[128];
int len = -1;
while (!isspace(*debugtext)) ++debugtext;
while (isspace(*debugtext)) ++debugtext;
ptr = debugtext;
while (!isspace(*debugtext)) ++debugtext;
len = debugtext-ptr;
/* filename */
strncpy(name, ptr, len);
name[len] = '\0';
/* bload addr */
while (isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, (char**)NULL, 16);
fp = fopen(name, "r");
if (fp == NULL) {
sprintf(second_buf[num_buffer_lines++], "problem: %s", name);
perror(name);
return BLOAD;
}
bload(fp, name, arg1);
fclose(fp);
return BLOAD;
}
{BOS}(st?e?p?|ne?x?t?){EOS} {
/* step / step next instruction */
if (*debugtext == 'n') step_next = 1;
c_do_step(1);
return STEP;
}
{BOS}(st?e?p?|ne?x?t?){WS}+{HEX}+{EOS} {
/* step / step next <n> instructions */
if (*debugtext == 'n') step_next = 1;
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, (char**)NULL, 16);
if ((arg1 < 1) || (arg1 > 255)) arg1 = 255;
c_do_step(arg1);
return STEP;
}
{BOS}fi?n?i?s?h?{EOS} {
int step_frame = 1;
unsigned char op;
/* step until finished with curent stack frame */
while ((c_mygetch(0) == -1) && !at_haltpt()) {
op = get_current_opcode();
if (op == 0x20) ++step_frame; /* JSR */
if (op == 0x60) --step_frame; /* RTS */
if (!step_frame) break; /* finished */
cpu65_step();
}
end_step(); /* print location */
return FINISH;
}
{BOS}un?t?i?l?{EOS} {
/* step until PC == next instruction. good for finishing backward
loops */
unsigned char op;
int delta;
op = get_current_opcode();
switch (opcodes[op].mode)
{
case addr_implied:
case addr_accumulator:
delta = 1;
break;
case addr_immediate:
case addr_zeropage:
case addr_zeropage_x:
case addr_zeropage_y:
case addr_indirect:
case addr_indirect_x:
case addr_indirect_y:
case addr_relative:
delta = 2;
break;
case addr_absolute:
case addr_absolute_x:
case addr_absolute_y:
case addr_j_indirect:
case addr_j_indirect_x:
delta = 3;
break;
}
arg1 = cpu65_current.pc + delta;
while ((cpu65_current.pc != arg1) && !at_haltpt() && (c_mygetch(0) == -1))
cpu65_step();
end_step(); /* print location */
return UNTIL;
}
{BOS}go?{WS}+{HEX}+{EOS} {
/* jump to addrs and run while remaining in debugger console */
while (!isspace(*debugtext)) ++debugtext;
/* DANGEROUS! */
cpu65_current.pc = strtol(debugtext, (char**)NULL, 16);
while (!at_haltpt() && (c_mygetch(0) == -1))
cpu65_step();
end_step(); /* print location */
return GO;
}
{BOS}go?{EOS} {
/* run while remaining in debugger console */
while (!at_haltpt() && (c_mygetch(0) == -1))
cpu65_step();
end_step(); /* print location */
return GO;
}
{BOS}wa?t?c?h?{EOS} {
/* set watchpoint */
set_halt(watchpoints, cpu65_current.pc);
return WATCH;
}
{BOS}wa?t?c?h?{WS}+{HEX}+{EOS} {
/* set watchpoint */
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, (char**)NULL, 16);
if ((arg1 < 0) || (arg1 > 65535)) {
sprintf(second_buf[num_buffer_lines++], "invalid address");
return WATCH;
}
set_halt(watchpoints, arg1);
return WATCH;
}
{BOS}br?e?a?k?{EOS} {
/* set breakpoint */
set_halt(breakpoints, cpu65_current.pc);
return BREAK;
}
{BOS}br?e?a?k?{WS}+{HEX}+{EOS} {
/* set breakpoint */
while (!isspace(*debugtext)) ++debugtext;
arg1 = strtol(debugtext, (char**)NULL, 16);
if ((arg1 < 0) || (arg1 > 65535)) {
sprintf(second_buf[num_buffer_lines++], "invalid address");
return BREAK;
}
set_halt(breakpoints, arg1);
return BREAK;
}
{BOS}br?e?a?k?{WS}*op{WS}+{HEX}+{EOS} {
/* set breakpoint */
while (!(*debugtext == 'p')) ++debugtext;
++debugtext;
arg1 = strtol(debugtext, (char**)NULL, 16);
if ((arg1 < 0) || (arg1 > 0xFF)) {
sprintf(second_buf[num_buffer_lines++], "invalid opcode");
return BREAK;
}
set_halt_opcode((unsigned char)arg1);
return BREAK;
}
#ifdef APPLE_IIE
{BOS}br65c02{EOS} {
/* set opcode breakpoints on 65c02 instructions */
set_halt_65c02();
return BREAK;
}
#endif
{BOS}ig?n?o?r?e?{EOS} {
/* ignore everything */
clear_halt(watchpoints, 0);
sprintf(second_buf[num_buffer_lines++], "ignored all");
return IGNORE;
}
{BOS}ig?n?o?r?e?({WS}+{DEC}+)+{EOS} {
/* ignore <watchpt> ... */
while (!isspace(*debugtext)) ++debugtext;
while (*debugtext) {
arg1 = strtol(debugtext, &debugtext, 10);
if ((arg1 < 1) || (arg1 > MAX_BRKPTS)) {
sprintf(second_buf[num_buffer_lines++], "invalid watchpoint");
return IGNORE;
}
clear_halt(watchpoints, arg1);
sprintf(second_buf[num_buffer_lines++], "ignored %d", arg1);
}
return IGNORE;
}
{BOS}cl?e?a?r?{EOS} {
/* clear everything */
clear_halt(breakpoints, 0);
sprintf(second_buf[num_buffer_lines++], "cleared all");
return CLEAR;
}
{BOS}cl?e?a?r?({WS}+{DEC}+)+{EOS} {
/* clear <breakpt> ... */
while (!isspace(*debugtext)) ++debugtext;
while (*debugtext) {
arg1 = strtol(debugtext, &debugtext, 10);
if ((arg1 < 1) || (arg1 > MAX_BRKPTS)) {
sprintf(second_buf[num_buffer_lines++], "invalid breakpoint");
return CLEAR;
}
clear_halt(breakpoints, arg1);
sprintf(second_buf[num_buffer_lines++], "cleared %d", arg1);
}
return CLEAR;
}
{BOS}cl?e?a?r?{WS}*op({WS}+{HEX}+)+{EOS} {
/* clear <opcode breakpt> ... */
while (!(*debugtext == 'p')) ++debugtext;
++debugtext;
while (*debugtext) {
arg1 = strtol(debugtext, &debugtext, 16);
if ((arg1 < 0) || (arg1 > 255)) {
sprintf(second_buf[num_buffer_lines++], "invalid opcode");
return CLEAR;
}
clear_halt_opcode((unsigned char)arg1);
sprintf(second_buf[num_buffer_lines++], "cleared opcode %02X",
(unsigned char)arg1);
}
return CLEAR;
}
#ifdef APPLE_IIE
{BOS}cl65c02{EOS} {
/* clear 65c02 ... */
clear_halt_65c02();
return CLEAR;
}
#endif
{BOS}stat?u?s?{EOS} {
/* show breakpoints and watchpoints */
show_breakpts();
return STATUS;
}
{BOS}opc?o?d?e?s?{EOS} {
/* show opcode breakpoints */
show_opcode_breakpts();
return OPCODES;
}
{BOS}sea?r?c?h?{WS}+{HEX}+{EOS} {
/* search main memory for <bytes> */
while (!isspace(*debugtext)) ++debugtext;
while (isspace(*debugtext)) ++debugtext;
search_mem(debugtext, 0, -1);
return SEARCH;
}
#ifdef APPLE_IIE
{BOS}sea?r?c?h?{WS}+{BANK}{WS}+{HEX}+{EOS} {
/* search memory<bank> for <bytes> */
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
while (isspace(*debugtext)) ++debugtext;
search_mem(debugtext, 0, arg3);
return SEARCH;
}
#endif
{BOS}sea?r?c?h?{WS}*(lc?1|lc?2){WS}+{HEX}+{EOS} {
/* search LC<bank> for <bytes> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (!isspace(*debugtext)) ++debugtext;
while (isspace(*debugtext)) ++debugtext;
search_mem(debugtext, lc, -1);
return SEARCH;
}
#ifdef APPLE_IIE
{BOS}sea?r?c?h?{WS}*(lc?1|lc?2){WS}+{BANK}{WS}+{HEX}+{EOS} {
/* search LC<bank> memory<bank> for <bytes> */
int lc;
while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext;
if (tolower(*debugtext) == 'c') ++debugtext;
lc = strtol(debugtext, &debugtext, 10);
while (*debugtext != '/') ++debugtext;
++debugtext; /* after / */
arg3 = strtol(debugtext, &debugtext, 10);
++debugtext; /* after / */
while (isspace(*debugtext)) ++debugtext;
search_mem(debugtext, lc, arg3);
return SEARCH;
}
#endif
{BOS}key{WS}+{HEX}+{EOS} {
/* send key code to emulator */
unsigned char key;
while (!isspace(*debugtext)) ++debugtext;
while (isspace(*debugtext)) ++debugtext;
key = (unsigned char) strtol(debugtext, &debugtext, 16);
apple_ii_64k[0][0xC000] = key;
apple_ii_64k[1][0xC000] = key;
}
{BOS}la?n?g?{EOS} {
/* display language card settings */
show_lc_info();
return LC;
}
{BOS}dri?v?e?{EOS} {
/* show disk settings */
show_disk_info();
return DRIVE;
}
{BOS}vm?{EOS} {
/* show other VM softswitch settings */
show_misc_info();
return VM;
}
{BOS}fre?s?h?{EOS} {
/* refresh the screen */
clear_debugger_screen();
}
{BOS}(\?|he?l?p?){EOS} {
display_help();
return HELP;
}
{BOS}bsave{WS}+{CHAR}+{WS}+{BANK}{ADDRS}{WS}+{HEX}+{EOS} {
/* bsave <file> /<bank>/<addr> <len> */
/* save memory dump to file */
FILE *fp = NULL;
char *ptr = NULL;
int len, start, len2, bank;
while (!isspace(*debugtext)) ++debugtext;
while (isspace(*debugtext)) ++debugtext;
/* copy file name */
ptr = debugtext;
while (!isspace(*debugtext)) ++debugtext;
len = debugtext - ptr;
strncpy(temp, ptr, len);
temp[len] = '\0';
/* get bank info */
while (*debugtext != '/') ++debugtext;
++debugtext;
bank = strtol(debugtext, &debugtext, 10);
++debugtext;
/* extract start and len */
start = strtol(debugtext, &debugtext, 16);
len2 = strtol(debugtext, &debugtext, 16);
fp = fopen(temp, "w"); /* try to open file for writing */
if (fp == NULL) {
sprintf(second_buf[num_buffer_lines++], "problem: %s", temp);
perror(temp);
return BSAVE;
}
len = fwrite(apple_ii_64k[bank]+start, 1, len2, fp);
if (len < len2) {
sprintf(second_buf[num_buffer_lines++], "problem: %s", temp);
perror(temp);
fclose(fp);
return BSAVE;
}
sprintf(second_buf[num_buffer_lines++], "bsaved: %s", temp);
fclose(fp);
return BSAVE;
}
{BOS}log{EOS} {
/* log debugger output to file - not implemented */
return LOG;
}
{BOS}save{EOS} {
/* save apple2 state to a .img file - not implemented I'd like to
* be compatible with the applePC emulator's .img format. anyone
* have documentation on this? -ASC
**/
return SAVE;
}
\n /* ignore newlines */
. /* ignore extraneous characters */
%%
int yywrap () {
return 1;
}
/* initialize the buffer - needed each time through */
void init_lex (char *str, int size) {
if (buffer) yy_delete_buffer(buffer);
buffer = yy_scan_buffer(str, size);
if (!buffer) { /* oops */
video_shutdown();
printf("lex buffer not big enough\n");
exit(1);
}
}

1135
src/debugger.c Normal file

File diff suppressed because it is too large Load Diff

671
src/disk.c Normal file
View File

@ -0,0 +1,671 @@
/*
* Apple // emulator for Linux: C portion of Disk ][ emulation
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>
#include "disk.h"
#include "misc.h"
#include "cpu.h"
#include "glue.h"
#include "prefs.h"
#define PHASE_BYTES 3328
static unsigned char slot6_rom[256];
static int slot6_rom_loaded = 0;
struct drive disk6;
static int skew_table_6[16] = /* Sector skew table */
{ 0,7,14,6,13,5,12,4,11,3,10,2,9,1,8,15 };
static int translate_table_6[256] =/* Translation table */
{
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01,
0x80, 0x80, 0x02, 0x03, 0x80, 0x04, 0x05, 0x06,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x07, 0x08,
0x80, 0x80, 0x80, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x80, 0x80, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
0x80, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x1b, 0x80, 0x1c, 0x1d, 0x1e,
0x80, 0x80, 0x80, 0x1f, 0x80, 0x80, 0x20, 0x21,
0x80, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x80, 0x80, 0x80, 0x80, 0x80, 0x29, 0x2a, 0x2b,
0x80, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
0x80, 0x80, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x80, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
};
/* -------------------------------------------------------------------------
c_init_6()
------------------------------------------------------------------------- */
void c_init_6()
{
disk6.disk[0].phase = disk6.disk[1].phase = 42;
disk6.disk[0].phase_change = disk6.disk[1].phase_change = 0;
disk6.motor = 1; /* motor on */
disk6.drive = 0; /* first drive active */
disk6.ddrw = 0;
disk6.volume = 254;
#if 0 /* BUGS!: */
file_name_6[0][1024] = '\0';
file_name_6[1][1024] = '\0';
#endif
}
/* -------------------------------------------------------------------------
c_eject_6() - assumes privileged access to image file (to re-gzip)
------------------------------------------------------------------------- */
void c_eject_6(int drive) {
pid_t pid;
if (disk6.disk[drive].compressed) {
/* gzip the last disk if it was compressed_6 */
if ((pid = fork())) { /* parent process */
/* privileged mode - gzip in place */
waitpid(pid, NULL, 0);
} else if (!pid) { /* child process */
/* privileged mode - gzip in place */
if (execl("/bin/gzip", "/bin/gzip",
disk6.disk[drive].file_name, NULL) == -1)
{
perror("Problem exec'ing /bin/gzip");
exit(-1);
}
} else {
perror("Problem calling fork" );
}
}
disk6.disk[drive].compressed = 0;
disk6.disk[drive].nibblized = 0;
sprintf(disk6.disk[drive].file_name, "%s", "");
if (disk6.disk[drive].fp) {
fclose(disk6.disk[drive].fp);
disk6.disk[drive].fp = NULL;
}
}
/* -------------------------------------------------------------------------
c_new_diskette_6( int drive, char *filename, Tr cmpr, Tr nib )
inserts a new disk image into the appropriate drive. assumes
privileged user level on entry, sets to the user when using disks.
return 1 if we can't open an image file for reading.
------------------------------------------------------------------------- */
int c_new_diskette_6(int drive, char *file_name, int cmpr, int nib, int force) {
struct stat buf;
strcpy(disk6.disk[drive].file_name, file_name);
disk6.disk[drive].compressed = cmpr;
disk6.disk[drive].nibblized = nib;
if (disk6.disk[drive].fp) {
fclose(disk6.disk[drive].fp);
disk6.disk[drive].fp = NULL;
}
/* set to users privilege level for disk access */
if (stat(disk6.disk[drive].file_name, &buf) < 0) {
disk6.disk[drive].fp = NULL;
c_eject_6(drive);
return 1; /* problem: disk unreadable */
}
else {
disk6.disk[drive].file_size = buf.st_size;
if (!force) {
/* Open read only */
disk6.disk[drive].fp = fopen(disk6.disk[drive].file_name, "r+");
disk6.disk[drive].protected = 0;
}
if ((disk6.disk[drive].fp == NULL) || (force)) {
/* Open for read AND write */
disk6.disk[drive].fp = fopen(disk6.disk[drive].file_name, "r");
disk6.disk[drive].protected = 1; /* disk is write protected! */
}
if (disk6.disk[drive].fp == NULL) {
/* Failed to open file. */
c_eject_6(drive);
return 1; /* problem: disk unreadable */
}
/* seek to current head position. */
fseek(disk6.disk[drive].fp, PHASE_BYTES * disk6.disk[drive].phase, SEEK_SET);
}
disk6.disk[drive].sector = 0;
disk6.disk[drive].run_byte = 0;
return 0; /* no problem */
}
/* -------------------------------------------------------------------------
c_read_nibblized_6_6() - reads a standard .nib file of length 232960 bytes.
there are 70 phases positioned every 3328 bytes.
------------------------------------------------------------------------- */
unsigned char c_read_nibblized_6_6()
{
static unsigned char ch;
if (disk6.disk[disk6.drive].phase_change) {
fseek(disk6.disk[disk6.drive].fp, PHASE_BYTES * disk6.disk[disk6.drive].phase, SEEK_SET);
disk6.disk[disk6.drive].phase_change = 0;
}
ch = (unsigned char) disk6.disk_byte = fgetc(disk6.disk[disk6.drive].fp);
/* track revolves... */
if (ftell(disk6.disk[disk6.drive].fp) == (PHASE_BYTES * (disk6.disk[disk6.drive].phase + 2)))
fseek(disk6.disk[disk6.drive].fp, -2 * PHASE_BYTES, SEEK_CUR);
return ch;
}
/* -------------------------------------------------------------------------
c_read_normal_6()
------------------------------------------------------------------------- */
unsigned char c_read_normal_6()
{
int position;
int old_value;
unsigned char value = 0;
/* The run byte tells what's to do */
switch (disk6.disk[disk6.drive].run_byte)
{
case 0: case 1: case 2: case 3: case 4: case 5:
case 20: case 21: case 22: case 23: case 24:
/* Sync */
value = 0xFF;
break;
case 6: case 25:
/* Prologue (first byte) */
value = 0xD5;
break;
case 7: case 26:
/* Prologue (second byte) */
value = 0xAA;
break;
case 8:
/* Prologue (third byte) */
value = 0x96;
break;
case 9:
/* Volume (encoded) */
value = (disk6.volume >> 1) | 0xAA;
disk6.checksum = disk6.volume;
break;
case 10:
/* Volume (encoded) */
value = disk6.volume | 0xAA;
break;
case 11:
/* Track number (encoded) */
disk6.checksum ^= (disk6.disk[disk6.drive].phase >> 1);
value = (disk6.disk[disk6.drive].phase >> 2) | 0xAA;
break;
case 12:
/* Track number (encoded) */
value = (disk6.disk[disk6.drive].phase >> 1) | 0xAA;
break;
case 13:
/* Sector number (encoded) */
disk6.checksum ^= disk6.disk[disk6.drive].sector;
value = (disk6.disk[disk6.drive].sector >> 1) | 0xAA;
break;
case 14:
/* Sector number (encoded) */
value = disk6.disk[disk6.drive].sector | 0xAA;
break;
case 15:
/* Checksum */
value = (disk6.checksum >> 1) | 0xAA;
break;
case 16:
/* Checksum */
value = disk6.checksum | 0xAA;
break;
case 17: case 371:
/* Epilogue (first byte) */
value = 0xDE;
break;
case 18: case 372:
/* Epilogue (second byte) */
value = 0xAA;
break;
case 19: case 373:
/* Epilogue (third byte) */
value = 0xEB;
break;
case 27:
/* Data header */
disk6.exor_value = 0;
/* Set file position variable */
disk6.disk[disk6.drive].file_pos = 256 * 16 * (disk6.disk[disk6.drive].phase >> 1) +
256 * skew_table_6[ disk6.disk[disk6.drive].sector ];
/* File large enough? */
if (disk6.disk[disk6.drive].file_pos + 255 > disk6.disk[disk6.drive].file_size)
return 0xFF;
/* Set position */
fseek( disk6.disk[disk6.drive].fp, disk6.disk[disk6.drive].file_pos, SEEK_SET );
/* Read sector */
fread( disk6.disk_data, 1, 256, disk6.disk[disk6.drive].fp );
disk6.disk_data[ 256 ] = disk6.disk_data[ 257 ] = 0;
value = 0xAD;
break;
case 370:
/* Checksum */
value = translate_table_6[disk6.exor_value & 0x3F];
/* Increment sector number (and wrap if necessary) */
disk6.disk[disk6.drive].sector++;
if (disk6.disk[disk6.drive].sector == 16)
disk6.disk[disk6.drive].sector = 0;
break;
default:
position = disk6.disk[disk6.drive].run_byte - 28;
if (position >= 0x56)
{
position -= 0x56;
old_value = disk6.disk_data[ position ];
old_value = old_value >> 2;
disk6.exor_value ^= old_value;
value = translate_table_6[disk6.exor_value & 0x3F];
disk6.exor_value = old_value;
}
else
{
old_value = 0;
old_value |= (disk6.disk_data[position] & 0x1) << 1;
old_value |= (disk6.disk_data[position] & 0x2) >> 1;
old_value |= (disk6.disk_data[position+0x56] & 0x1) << 3;
old_value |= (disk6.disk_data[position+0x56] & 0x2) << 1;
old_value |= (disk6.disk_data[position+0xAC] & 0x1) << 5;
old_value |= (disk6.disk_data[position+0xAC] & 0x2) << 3;
disk6.exor_value ^= old_value;
value = translate_table_6[disk6.exor_value & 0x3F];
disk6.exor_value = old_value;
}
break;
} /* End switch */
/* Continue by increasing run byte value */
disk6.disk[disk6.drive].run_byte++;
if (disk6.disk[disk6.drive].run_byte > 373)
disk6.disk[disk6.drive].run_byte = 0;
disk6.disk_byte = value;
return value;
}
/* -------------------------------------------------------------------------
c_write_nibblized_6_6() - writes a standard .nib file of length 232960 bytes.
there are 70 phases positioned every 3328 bytes.
------------------------------------------------------------------------- */
void c_write_nibblized_6_6()
{
if (disk6.disk[disk6.drive].phase_change) {
fseek(disk6.disk[disk6.drive].fp, PHASE_BYTES * disk6.disk[disk6.drive].phase, SEEK_SET);
disk6.disk[disk6.drive].phase_change = 0;
}
fputc(disk6.disk_byte, disk6.disk[disk6.drive].fp);
/* track revolves... */
if (ftell(disk6.disk[disk6.drive].fp) == (PHASE_BYTES * (disk6.disk[disk6.drive].phase + 2)))
fseek(disk6.disk[disk6.drive].fp, -2 * PHASE_BYTES, SEEK_CUR);
}
/* -------------------------------------------------------------------------
c_write_normal_6() disk6.disk_byte contains the value
------------------------------------------------------------------------- */
void c_write_normal_6()
{
int position;
int old_value;
if (disk6.disk_byte == 0xD5)
disk6.disk[disk6.drive].run_byte = 6; /* Initialize run byte value */
/* The run byte tells what's to do */
switch (disk6.disk[disk6.drive].run_byte)
{
case 0: case 1: case 2: case 3: case 4: case 5:
case 20: case 21: case 22: case 23: case 24:
/* Sync */
break;
case 6: case 25:
/* Prologue (first byte) */
if (disk6.disk_byte == 0xFF)
disk6.disk[disk6.drive].run_byte--;
break;
case 7: case 26:
/* Prologue (second byte) */
break;
case 8:
/* Prologue (third byte) */
if (disk6.disk_byte == 0xAD)
disk6.exor_value = 0, disk6.disk[disk6.drive].run_byte = 27;
break;
case 9: case 10:
/* Volume */
break;
case 11: case 12:
/* Track */
break;
case 13: case 14:
/* Sector */
break;
case 15:
/* Checksum */
break;
case 16:
/* Checksum */
break;
case 17: case 371:
/* Epilogue (first byte) */
break;
case 18: case 372:
/* Epilogue (second byte) */
break;
case 19: case 373:
/* Epilogue (third byte) */
break;
case 27:
disk6.exor_value = 0;
break;
case 370:
/* Set file position variable */
disk6.disk[disk6.drive].file_pos = 256 * 16 * (disk6.disk[disk6.drive].phase >> 1) +
256 * skew_table_6[ disk6.disk[disk6.drive].sector ];
/* Is the file large enough? */
if (disk6.disk[disk6.drive].file_pos + 255 > disk6.disk[disk6.drive].file_size)
return;
/* Set position */
fseek( disk6.disk[disk6.drive].fp, disk6.disk[disk6.drive].file_pos, SEEK_SET );
/* Write sector */
fwrite(disk6.disk_data, 1, 256, disk6.disk[disk6.drive].fp);
fflush( disk6.disk[disk6.drive].fp );
/* Increment sector number (and wrap if necessary) */
disk6.disk[disk6.drive].sector++;
if (disk6.disk[disk6.drive].sector == 16)
disk6.disk[disk6.drive].sector = 0;
break;
default:
position = disk6.disk[disk6.drive].run_byte - 28;
disk6.disk_byte = translate_table_6[ disk6.disk_byte ];
if (position >= 0x56)
{
position -= 0x56;
disk6.disk_byte ^= disk6.exor_value;
old_value = disk6.disk_byte;
disk6.disk_data[position] |= (disk6.disk_byte << 2) & 0xFC;
disk6.exor_value = old_value;
}
else
{
disk6.disk_byte ^= disk6.exor_value;
old_value = disk6.disk_byte;
disk6.disk_data[position] = (disk6.disk_byte & 0x01) << 1;
disk6.disk_data[position] |= (disk6.disk_byte & 0x02) >> 1;
disk6.disk_data[position + 0x56] = (disk6.disk_byte & 0x04) >> 1;
disk6.disk_data[position + 0x56] |= (disk6.disk_byte & 0x08) >> 3;
disk6.disk_data[position + 0xAC] = (disk6.disk_byte & 0x10) >> 3;
disk6.disk_data[position + 0xAC] |= (disk6.disk_byte & 0x20) >> 5;
disk6.exor_value = old_value;
}
break;
} /* End switch */
disk6.disk[disk6.drive].run_byte++;
if (disk6.disk[disk6.drive].run_byte > 373)
disk6.disk[disk6.drive].run_byte = 0;
}
GLUE_C_READ(disk_read_byte)
{
if (disk6.ddrw)
{
if (disk6.disk[disk6.drive].fp == NULL)
return 0; /* Return if there is no disk in drive */
if (disk6.disk[disk6.drive].protected)
return 0; /* Do not write if diskette is write protected */
if (disk6.disk_byte < 0x96)
return 0; /* Only byte values at least 0x96 are allowed */
(disk6.disk[disk6.drive].nibblized) ? c_write_nibblized_6_6() : c_write_normal_6();
return 0; /* ??? */
}
else
{
if (disk6.disk[disk6.drive].fp == NULL)
return 0xFF; /* Return FF if there is no disk in drive */
if (disk6.motor) /* Motor turned on? */
{
if (disk6.motor > 99)
return 0;
else
disk6.motor++;
}
/* handle nibblized_6 or regular disks */
return (disk6.disk[disk6.drive].nibblized) ? c_read_nibblized_6_6() : c_read_normal_6() ;
}
}
GLUE_C_READ(disk_read_phase)
{
/*
* Comment from xapple2+ by Phillip Stephens:
* Turn motor phases 0 to 3 on. Turning on the previous phase + 1
* increments the track position, turning on the previous phase - 1
* decrements the track position. In this scheme phase 0 and 3 are
* considered to be adjacent. The previous phase number can be
* computed as the track number % 4.
*/
switch (((ea >> 1) - disk6.disk[disk6.drive].phase) & 3)
{
case 1:
disk6.disk[disk6.drive].phase++;
break;
case 3:
disk6.disk[disk6.drive].phase--;
break;
}
if (disk6.disk[disk6.drive].phase<0) disk6.disk[disk6.drive].phase=0;
if (disk6.disk[disk6.drive].phase>69) disk6.disk[disk6.drive].phase=69;
disk6.disk[disk6.drive].phase_change = 1;
return 0;
}
GLUE_C_READ(disk_read_motor_off)
{
disk6.motor = 1;
return disk6.drive;
}
GLUE_C_READ(disk_read_motor_on)
{
disk6.motor = 0;
return disk6.drive;
}
GLUE_C_READ(disk_read_select_a)
{
return disk6.drive = 0;
}
GLUE_C_READ(disk_read_select_b)
{
return disk6.drive = 1;
}
GLUE_C_READ(disk_read_latch)
{
return disk6.drive;
}
GLUE_C_READ(disk_read_prepare_in)
{
disk6.ddrw = 0;
return disk6.disk[disk6.drive].protected ? 0x80 : 0x00;
}
GLUE_C_READ(disk_read_prepare_out)
{
disk6.ddrw = 1;
return disk6.drive;
}
GLUE_C_WRITE(disk_write_latch)
{
disk6.disk_byte = d;
}
void disk_install(int slot)
{
FILE *f;
int i;
assert(slot == 6);
/* load Disk II rom */
if (!slot6_rom_loaded) {
snprintf(temp, TEMPSIZE, "%s/slot6.rom", system_path);
if ((f = fopen( temp, "r" )) == NULL) {
printf("Cannot find file '%s'.\n",temp);
exit( 0 );
}
fread(slot6_rom, 0x100, 1, f);
fclose(f);
slot6_rom_loaded = 1;
}
memcpy(apple_ii_64k[0] + 0xC600, slot6_rom, 0x100);
/* disk softswitches */
cpu65_vmem[0xC0E0].r = cpu65_vmem[0xC0E2].r =
cpu65_vmem[0xC0E4].r = cpu65_vmem[0xC0E6].r =
ram_nop;
cpu65_vmem[0xC0E1].r = cpu65_vmem[0xC0E3].r =
cpu65_vmem[0xC0E5].r = cpu65_vmem[0xC0E7].r =
disk_read_phase;
cpu65_vmem[0xC0E8].r =
disk_read_motor_off;
cpu65_vmem[0xC0E9].r =
disk_read_motor_on;
cpu65_vmem[0xC0EA].r =
disk_read_select_a;
cpu65_vmem[0xC0EB].r =
disk_read_select_b;
cpu65_vmem[0xC0EC].r =
disk_read_byte;
cpu65_vmem[0xC0ED].r =
disk_read_latch; /* read latch */
cpu65_vmem[0xC0EE].r =
disk_read_prepare_in;
cpu65_vmem[0xC0EF].r =
disk_read_prepare_out;
for (i = 0xC0E0; i < 0xC0F0; i++) {
cpu65_vmem[i].w =
cpu65_vmem[i].r;
}
cpu65_vmem[0xC0ED].w =
disk_write_latch; /* write latch */
}

67
src/disk.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Apple // emulator for Linux: Defines for Disk ][ emulation
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_DISK_H
struct diskette
{
unsigned char file_name[1024];
int compressed;
int nibblized;
int protected;
int phase_change;
int sector;
long file_size;
int phase;
int run_byte;
FILE *fp;
int file_pos;
};
struct drive
{
int motor;
int drive;
int ddrw;
int disk_byte;
int volume;
int checksum;
int exor_value;
unsigned char disk_data[258];
struct diskette disk[2];
};
extern struct drive disk6;
void c_init_6();
int c_new_diskette_6(int, char*, int, int, int);
void c_eject_6(int);
void disk_read_nop(),
disk_read_phase(),
disk_read_motor_off(),
disk_read_motor_on(),
disk_read_select_a(),
disk_read_select_b(),
disk_read_byte(),
disk_read_latch(),
disk_write_latch(),
disk_read_prepare_in(),
disk_read_prepare_out();
#define A2_DISK_H
#endif

1238
src/display.S Normal file

File diff suppressed because it is too large Load Diff

1276
src/font.txt Normal file

File diff suppressed because it is too large Load Diff

115
src/genfont.c Normal file
View File

@ -0,0 +1,115 @@
/*
* Apple // emulator for Linux: Font compiler
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define _GNU_SOURCE
/* I'm not sure if this is the correct way to detect libc 5/4. I long
* since removed it from my system.
*/
#ifdef __GLIBC__
#if __GLIBC__ == 1
/* Older Linux C libraries had getline removed (to humor programs that
* used that name for their own functions), but kept getdelim */
#define getline(l,s,f) getdelim(l,s,'\n',f)
#endif /* __GLIBC__ == 1 */
#endif /* __GLIBC__ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
unsigned char byte;
char *line = 0;
size_t line_size = 0;
int i,mx;
printf("/* Apple II text font data\n"
" * \n"
" * THIS FILE IS AUTOMATICALLY GENERATED --- DO NOT EDIT\n"
" */\n");
i = 0x100;
while (getline(&line,&line_size,stdin) != -1)
{
if (line[0] == ';') continue;
if (line[0] == '=')
{
char *name,*size;
name = line + 1;
while (isspace(*name)) name++;
size = strchr(name,',');
*size++ = 0;
mx = i = strtol(size,0,0);
printf("\nconst unsigned char %s[%d] =\n{\n ",name,i*8);
continue;
}
i--;
if (line[0] == ':')
{
int j = 8;
while (j--)
{
int k;
getline(&line,&line_size,stdin);
k = 8;
byte = 0;
while (k--)
{
byte <<= 1;
byte += (line[k] == '#');
}
if (j)
printf("0x%02x, ",byte);
else if (i)
printf("0x%02x,\n ",byte); /* last byte in glyph */
else
printf("0x%02x\n};\n",byte); /* last item in array */
}
}
else break;
}
if (i)
{
fprintf(stderr,
"Trouble with font file at character 0x%02x\n",
mx-i-1);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

5
src/genglue Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh
echo '/* Automatically Generated -- do not edit */'
echo '#include "gluepro.h"'
grep -E -h '^(GLUE_)|(#if)|(#endif)|(#else)|(#elif)' $*
exit 0

28
src/glue.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Apple // emulator for Linux: Glue macros
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define GLUE_FIXED_READ(func,address)
#define GLUE_FIXED_WRITE(func,address)
#define GLUE_BANK_READ(func,pointer)
#define GLUE_BANK_WRITE(func,pointer)
#define GLUE_BANK_MAYBEWRITE(func,pointer)
#define GLUE_C_WRITE(func) \
void unglued_##func(int ea, unsigned char d) /* you complete definition */
#define GLUE_C_READ(func) \
unsigned char unglued_##func(int ea) /* you complete definition */

75
src/gluepro.h Normal file
View File

@ -0,0 +1,75 @@
/*
* Apple // emulator for Linux: Glue file prologue for Intel 386
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define __ASSEMBLY__
#include <apple2.h>
#define GLUE_FIXED_READ(func,address) \
E(func) movb SN(address)(%edi),%al; \
ret;
#define GLUE_FIXED_WRITE(func,address) \
E(func) movb %al,SN(address)(%edi); \
ret;
#define GLUE_BANK_READ(func,pointer) \
E(func) addl SN(pointer),%edi; \
movb (%edi),%al; \
subl SN(pointer),%edi; \
ret;
#define GLUE_BANK_WRITE(func,pointer) \
E(func) addl SN(pointer),%edi; \
movb %al,(%edi); \
subl SN(pointer),%edi; \
ret;
#define GLUE_BANK_MAYBEWRITE(func,pointer) \
E(func) addl SN(pointer),%edi; \
cmpl $0,SN(pointer); \
jz 1f; \
movb %al,(%edi); \
1: ret;
#define GLUE_C_WRITE(func) \
E(func) pushl %eax; \
andl $0xff,%eax; \
pushl %ecx; \
pushl %edx; \
pushl %eax; \
pushl %edi; \
call SN(unglued_##func); \
popl %edx; /* dummy */ \
popl %edx; /* dummy */ \
popl %edx; \
popl %ecx; \
popl %eax; \
ret; \
#define GLUE_C_READ(func) \
E(func) pushl %eax; \
pushl %ecx; \
pushl %edx; \
pushl %edi; \
call SN(unglued_##func); \
movb %al,12(%esp); \
popl %edx; /* dummy */ \
popl %edx; \
popl %ecx; \
popl %eax; \
ret;

1229
src/interface.c Normal file

File diff suppressed because it is too large Load Diff

28
src/interface.h Normal file
View File

@ -0,0 +1,28 @@
/*
* Apple // emulator for Linux: Exported menu routines
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_INTERFACE_H
#define A2_INTERFACE_H
void c_interface_print( int x, int y, int cs, unsigned char *s );
void c_interface_redo_bottom();/* bit of a HACK? */
void c_load_interface_font();
void c_interface_keyboard_layout();
void c_interface_parameters();
void c_interface_exit();
void c_interface_translate_screen(unsigned char screen[24][41]);
void c_interface_select_diskette(int);
#endif

207
src/joystick.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Apple // emulator for Linux: Joystick calibration routines
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <linux/joystick.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <values.h>
#include "interface.h"
#include "video.h"
#include "keys.h"
#include "misc.h"
#include "prefs.h"
int js_fd = -1; /* joystick file descriptor */
struct JS_DATA_TYPE js; /* joystick data struct */
int js_lowerrange_x,
js_upperrange_x,
js_lowerrange_y,
js_upperrange_y,
js_offset_x,
js_offset_y;
float
js_adjustlow_x,
js_adjustlow_y,
js_adjusthigh_x,
js_adjusthigh_y;
/* -------------------------------------------------------------------------
c_open_joystick() - opens joystick device and sets timelimit value
------------------------------------------------------------------------- */
int c_open_joystick() {
if (js_fd < 0) {
if ((js_fd = open("/dev/js0", O_RDONLY)) < 0) {
/* try again with another name */
if ((js_fd = open("/dev/joystick", O_RDONLY)) < 0)
return 1;/* problem */
}
/* set timelimit value */
if (ioctl(js_fd, JS_SET_TIMELIMIT, &js_timelimit) == -1)
return 1;/* problem */
}
return 0;/* no problem */
}
/* -------------------------------------------------------------------------
c_close_joystick() - closes joystick device
------------------------------------------------------------------------- */
void c_close_joystick() {
if (js_fd < 0)
return;
close(js_fd);
js_fd = -1;
}
/* -------------------------------------------------------------------------
* c_calculate_joystick_parms() - calculates parameters for joystick
* device. assumes that device extremes have already been determined.
* ------------------------------------------------------------------------- */
void c_calculate_joystick_parms() {
js_lowerrange_x = js_center_x - js_min_x;
js_upperrange_x = js_max_x - js_center_x;
js_lowerrange_y = js_center_y - js_min_y;
js_upperrange_y = js_max_y - js_center_y;
js_offset_x = js_min_x;
js_offset_y = js_min_y;
js_adjustlow_x = (float)half_joy_range / (float)js_lowerrange_x;
js_adjustlow_y = (float)half_joy_range / (float)js_lowerrange_y;
js_adjusthigh_x = (float)half_joy_range / (float)js_upperrange_x;
js_adjusthigh_y = (float)half_joy_range / (float)js_upperrange_y;
}
/* -------------------------------------------------------------------------
c_calibrate_joystick() - calibrates joystick. determines extreme
and center coordinates. assumes that it can write to the interface
screen.
------------------------------------------------------------------------- */
void c_calibrate_joystick () {
int almost_done, done;
unsigned char x_val, y_val;
/* reset all the extremes */
js_max_x = -1;
js_max_y = -1;
js_min_x = MAXINT;
js_min_y = MAXINT;
/* open joystick device if not open */
if (js_fd < 0) {
if (c_open_joystick()) { /* problem opening device */
c_interface_print(
1, 21, 0, " " );
c_interface_print(
1, 22, 0, " cannot open joystick device. " );
video_sync(0);
usleep(1500000);
c_interface_redo_bottom();
return;/* problem */
}
}
c_interface_print(
1, 21, 0, " Move joystick to all extremes then " );
c_interface_print(
1, 22, 0, " center it and press a button. " );
video_sync(0);
usleep(1500000);
c_interface_print(
1, 21, 0, " " );
c_interface_print(
1, 22, 0, " " );
almost_done = done = 0; /* not done calibrating */
while ((read(js_fd, &js, JS_RETURN) > 0) && (!done))
{
sprintf (temp, " x = %04x, y = %04x", js.x, js.y);
c_interface_print(1, 22, 0, temp);
video_sync(0);
if (js_max_x < js.x)
js_max_x = js.x;
if (js_max_y < js.y)
js_max_y = js.y;
if (js_min_x > js.x)
js_min_x = js.x;
if (js_min_y > js.y)
js_min_y = js.y;
if (js.buttons != 0x00) /* press */
almost_done = 1;
if (almost_done && (js.buttons == 0x00)) /* release */
done = 1;
}
js_center_x = js.x;
js_center_y = js.y;
printf("js_min_x = %d\n", js_min_x);
printf("js_min_y = %d\n", js_min_y);
printf("js_max_x = %d\n", js_max_x);
printf("js_max_y = %d\n", js_max_y);
printf("js_center_x = %d\n", js_center_x);
printf("js_center_y = %d\n", js_center_y);
printf("\n");
c_calculate_joystick_parms(); /* determine the parms */
printf("js_lowerrange_x = %d\n", js_lowerrange_x);
printf("js_lowerrange_y = %d\n", js_lowerrange_y);
printf("js_upperrange_x = %d\n", js_upperrange_x);
printf("js_upperrange_y = %d\n", js_upperrange_y);
printf("\n");
printf("js_offset_x = %d\n", js_offset_x);
printf("js_offset_y = %d\n", js_offset_y);
printf("\n");
printf("js_adjustlow_x = %f\n", js_adjustlow_x);
printf("js_adjustlow_y = %f\n", js_adjustlow_y);
printf("js_adjusthigh_x = %f\n", js_adjusthigh_x);
printf("js_adjusthigh_y = %f\n", js_adjusthigh_y);
printf("\n");
c_interface_print(
1, 21, 0, " Press a button to continue. " );
video_sync(0);
/* show the normalized values until user presses button */
while ((read(js_fd, &js, JS_RETURN) > 0) && js.buttons == 0x00) {
x_val = (js.x < js_center_x)
? (js.x - js_offset_x) * js_adjustlow_x
: (js.x - (js_center_x/*+js_offset_x*/)) * js_adjusthigh_x +
half_joy_range;
y_val = (js.y < js_center_y)
? (js.y - js_offset_y) * js_adjustlow_y
: (js.y - (js_center_y/*+js_offset_y*/)) * js_adjusthigh_y +
half_joy_range;
sprintf(temp, " x = %02x, y = %02x", x_val, y_val);
c_interface_print(1, 22, 0, temp);
video_sync(0);
}
c_interface_redo_bottom();
video_sync(0);
}

461
src/keys.c Normal file
View File

@ -0,0 +1,461 @@
/*
* Apple // emulator for Linux: Keyboard handler
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/keyboard.h>
#include "keys.h"
#include "misc.h"
#include "video.h"
#include "interface.h"
#include "cpu.h"
#include "prefs.h"
/* from misc.c */
extern uid_t user, privileged;
#ifdef DEBUGGER
/* from debugger.c */
extern void c_do_debugging();
#endif
/* parameters for generic and keyboard-simulated joysticks */
short joy_x = 127;
short joy_y = 127;
unsigned char joy_button0 = 0;
unsigned char joy_button1 = 0;
unsigned char joy_button2 = 0;
#ifdef PC_JOYSTICK
#include <linux/joystick.h>
int x_val, y_val;
#endif
static int next_key = -1;
static char caps_lock = 1; /* is enabled */
static int in_mygetch = 0;
/* ----------------------------------------------------
Keymap. Mapping scancodes to Apple II+ US Keyboard
---------------------------------------------------- */
static int apple_ii_keymap_plain[128] =
{ -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */
'7', '8', '9', '0', ':', '-', 8 , 27 , /* 08-15 */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */
'O', 'P', -1 , 8 , 13 , -1 , 'A', 'S', /* 24-31 */
'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 32-39 */
8 , -1 , -1 , 21 , 'Z', 'X', 'C', 'V', /* 40-47 */
'B', 'N', 'M', ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , -1, JB1 , RST , kHOME , -1 , /* 96-103 */
kPGUP , 8 , 21 , kEND , -1 , kPGDN, JB2 , -1, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* (pause) */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_ii_keymap_ctrl[128] =
{ -1 , 027, '1', '2', '3', '4', '5', '6', /* 00-07 */
'7', '8', '9', '0', ':', '-', 8 , 27 , /* 08-15 */
17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */
15 , 16 , -1 , 8 , 13 , -1 , 1 , 19 , /* 24-31 */
4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */
8 , -1 , -1 , 21 , 26 , 24 , 3 , 22 , /* 40-47 */
2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , BOT, JB1 , RST , kHOME , -1 , /* 96-103 */
kPGUP , 8 , 21 , kEND, -1 , kPGDN, JB2 , -1, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_ii_keymap_shifted[128] =
{ -1 , 27 , '!', '"', '#', '$', '%', '&', /* 00-07 */
39 , '(', ')', '0', '*', '=', 8 , 27 , /* 08-15 */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */
'O', '@', -1 , 8 , 13 , -1 , 'A', 'S', /* 24-31 */
'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', /* 32-39 */
8 , -1 , -1 , 21 , 'Z', 'X', 'C', 'V', /* 40-47 */
'B', '^', 'M', '<', '>', '?', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , -1 , JB1 , RST , kHOME , -1 , /* 96-103 */
kPGUP , 8 , 21 , kEND, -1 , kPGDN, JB2 , -1, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
#ifdef APPLE_IIE
/* ----------------------------------------------------
//e Keymap. Mapping scancodes to Apple //e US Keyboard
---------------------------------------------------- */
static int apple_iie_keymap_plain[128] =
{ -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */
'7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 16-23 */
'o', 'p', '[', ']', 13 , -1 , 'a', 's', /* 24-31 */
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 32-39 */
'\'', '`', -1 ,'\\', 'z', 'x', 'c', 'v', /* 40-47 */
'b', 'n', 'm', ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , -1, JB1 , RST , kHOME , 11 , /* 96-103 */
kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_iie_keymap_ctrl[128] =
{ -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */
'7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */
17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */
15 , 16 , 27 , 29 , 13 , -1 , 1 , 19 , /* 24-31 */
4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */
'\'', '`', -1 ,'\\', 26 , 24 , 3 , 22 , /* 40-47 */
2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , BOT, JB1 , RST , kHOME , 11 , /* 96-103 */
kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_iie_keymap_shifted[128] =
{ -1 , 27 , '!', '@', '#', '$', '%', '^', /* 00-07 */
'&', '*', '(', ')', '_', '+', 8 , 9 , /* 08-15 */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */
'O', 'P', '{', '}', 13 , -1 , 'A', 'S', /* 24-31 */
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 32-39 */
'"', '~', -1 , '|', 'Z', 'X', 'C', 'V', /* 40-47 */
'B', 'N', 'M', '<', '>', '?', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , -1 , JB1 , RST , kHOME , 11 , /* 96-103 */
kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_iie_keymap_caps[128] =
{ -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */
'7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */
'O', 'P', '[', ']', 13 , -1 , 'A', 'S', /* 24-31 */
'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 32-39 */
'\'', '`', -1 ,'\\', 'Z', 'X', 'C', 'V', /* 40-47 */
'B', 'N', 'M', ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , -1, JB1 , RST , kHOME , 11 , /* 96-103 */
kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
static int apple_iie_keymap_shift_ctrl[128] =
{ -1 , 27 , '1', 0 , '3', '4', '5', 30 , /* 00-07 */
'7', '8', '9', '0', 31 , '=', 8 , 9 , /* 08-15 */
17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */
15 , 16 , 27 , 29 , 13 , -1 , 1 , 19 , /* 24-31 */
4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */
'\'', '`', 28 , -1 , 26 , 24 , 3 , 22 , /* 40-47 */
2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */
JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */
kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */
J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */
J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */
-1 , -1 , -1 , BOT, JB1 , RST , kHOME , 11 , /* 96-103 */
kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */
#endif
static unsigned short max_speed = 0;
static char key_pressed[ 256 ];
/* ----------------------------------------------------
functions
---------------------------------------------------- */
/* -------------------------------------------------------------------------
* This routine is called periodically to update the state of the emulator.
* -handles switching to menus
* -polls PC Joystick
* -update palette for flashing text
* ------------------------------------------------------------------------- */
void c_periodic_update(int dummysig) {
int current_key;
video_sync(0);
if (next_key >= 0)
{
current_key = next_key;
next_key = -1;
if (current_key < 128) {
apple_ii_64k[0][0xC000] = current_key | 0x80;
apple_ii_64k[1][0xC000] = current_key | 0x80;
} else switch (current_key) {
case RST:
cpu65_interrupt(ResetSig);
break;
case BOT:
cpu65_interrupt(RebootSig);
break;
case J_C:
joy_x = joy_center_x;
joy_y = joy_center_y;
break;
case kF1:
c_interface_select_diskette( 0 );
break;
case kF2:
c_interface_select_diskette( 1 );
break;
case kF4:
while (c_mygetch(1) == -1) { }/*busy loop*/
break;
case kF5:
c_interface_keyboard_layout();
break;
#ifdef DEBUGGER
case kF7:
cpu65_interrupt(EnterDebugSig);
break;
#endif
#if 0
case kF8:
c_interface_words();
break;
#endif
case kF9:
if (max_speed != 0)
cpu65_delay = max_speed, max_speed = 0;
else
max_speed = cpu65_delay, cpu65_delay = 1;
break;
case kF10:
if (max_speed != 0)
cpu65_delay = max_speed, max_speed = 0;
c_interface_parameters();
break;
}
}
/* simulated joystick */
if (joy_mode == JOY_KYBD) {
if (key_pressed[ SCODE_J_U ])
{
if (joy_y > joy_step)
joy_y -= joy_step;
else
joy_y = 0;
}
if (key_pressed[ SCODE_J_D ])
{
if (joy_y < joy_range - joy_step)
joy_y += joy_step;
else
joy_y = joy_range-1;
}
if (key_pressed[ SCODE_J_L ])
{
if (joy_x > joy_step)
joy_x -= joy_step;
else
joy_x = 0;
}
if (key_pressed[ SCODE_J_R ])
{
if (joy_x < joy_range - joy_step)
joy_x += joy_step;
else
joy_x = joy_range-1;
}
}
#ifdef PC_JOYSTICK
else if ((joy_mode == JOY_PCJOY) && !(js_fd < 0)) {
read(js_fd, &js, JS_RETURN);
x_val = (js.x < js_center_x)
? (js.x - js_offset_x) * js_adjustlow_x
: (js.x - js_center_x) * js_adjusthigh_x + half_joy_range;
y_val = (js.y < js_center_y)
? (js.y - js_offset_y) * js_adjustlow_y
: (js.y - js_center_y) * js_adjusthigh_y + half_joy_range;
joy_y = (y_val > 0xff) ? 0xff : (y_val < 0) ? 0 : y_val;
joy_x = (x_val > 0xff) ? 0xff : (x_val < 0) ? 0 : x_val;
/* almost_x = (x_val > 0xff) ? 0xff : (x_val < 0) ? 0 : x_val; */
/* adj_x = (3-(joy_y/0x40)) + 10; */
/* turnpt_x = joy_y + adj_x; */
/* almost_x = (almost_x < turnpt_x) */
/* ? almost_x */
/* : (almost_x - turnpt_x) * adjusthigh_x; */
/* joy_x = (almost_x > 0xff) ? 0xff : (almost_x < 0) ? 0 : almost_x; */
/* sample buttons only if apple keys aren't pressed. keys get set to
* 0xff, and js buttons are set to 0x80. */
if (!(joy_button0 & 0x7f))
joy_button0 = (js.buttons & 0x01) ? 0x80 : 0x0;
if (!(joy_button1 & 0x7f))
joy_button1 = (js.buttons & 0x02) ? 0x80 : 0x0;
if (!(joy_button2 & 0x7f))
joy_button2 = (js.buttons & 0x03) ? 0x80 : 0x0;
}
#endif
else if (joy_mode == JOY_OFF)
joy_x = joy_y = 256;
}
#ifdef DEBUGGER
/* Called from cpu code. Perhaps should be moved to misc.c, but was
* abstracted from function above...
*/
void enter_debugger(void)
{
setitimer(ITIMER_VIRTUAL,&timer_off,0);
c_do_debugging();
setitimer(ITIMER_VIRTUAL,&timer_on,0);
}
#endif /* DEBUGGER */
/* -------------------------------------------------------------------------
void c_read_raw_key() : handle a scancode
------------------------------------------------------------------------- */
void c_read_raw_key(int scancode, int pressed) {
int *keymap = NULL;
/* determine which key mapping to use */
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE || in_mygetch) {
/* set/reset caps lock */
if (key_pressed[ SCODE_CAPS ])
caps_lock = !caps_lock;
if ((key_pressed[ SCODE_L_SHIFT ] || /* shift-ctrl */
key_pressed[ SCODE_R_SHIFT ]) &&
(key_pressed[ SCODE_L_CTRL ] ||
key_pressed[ SCODE_R_CTRL ]))
keymap = apple_iie_keymap_shift_ctrl;
else if (key_pressed[ SCODE_L_CTRL ] || /* ctrl */
key_pressed[ SCODE_R_CTRL ])
keymap = apple_iie_keymap_ctrl;
else if (key_pressed[ SCODE_L_SHIFT ] || /* shift */
key_pressed[ SCODE_R_SHIFT ])
keymap = apple_iie_keymap_shifted;
else if (caps_lock) /* caps lock */
keymap = apple_iie_keymap_caps;
else /* plain */
keymap = apple_iie_keymap_plain;
} else
#endif
{
if (key_pressed[ SCODE_L_CTRL ] ||
key_pressed[ SCODE_R_CTRL ])
keymap = apple_ii_keymap_ctrl;
else if (key_pressed[ SCODE_L_SHIFT ] ||
key_pressed[ SCODE_R_SHIFT ])
keymap = apple_ii_keymap_shifted;
else
keymap = apple_ii_keymap_plain;
}
/* key is pressed */
if (pressed) {
key_pressed[ scancode ] = 1;
switch (keymap[ scancode ]) {
case JB0:
joy_button0 = 0xff;/* open apple */
break;
case JB1:
joy_button1 = 0xff;/* closed apple */
break;
case JB2:
joy_button2 = 0xff;/* unused? */
break;
default:
next_key = keymap[scancode];
break;
}
}
/* key is released */
else {
key_pressed[ scancode ] = 0;
switch (keymap[ scancode ]) {
case JB0:
joy_button0 = 0x00;
break;
case JB1:
joy_button1 = 0x00;
break;
case JB2:
joy_button2 = 0x00;
break;
}
}
}
int c_mygetch(int block)
{
int retval;
in_mygetch = 1;
if (block) while (next_key == -1)
video_sync(1);
else
video_sync(0);
in_mygetch = 0;
retval = next_key;
next_key = -1;
return retval;
}

95
src/keys.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Apple // emulator for Linux: Keyboard definitions
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_KEYS_H
#define A2_KEYS_H
#define SCODE_L_CTRL 29
#define SCODE_R_CTRL 97
#define SCODE_L_SHIFT 42
#define SCODE_R_SHIFT 54
#define SCODE_CAPS 58
#define SCODE_J_U 72
#define SCODE_J_D 80
#define SCODE_J_L 75
#define SCODE_J_R 77
#define SCODE_J_C 76
#define kF1 128
#define kF2 129
#define kF3 130
#define kF4 131
#define kF5 132
#define kF6 133
#define kF7 134
#define kF8 135
#define kF9 136
#define kF10 137
#define kF11 138
#define kF12 139
#define kPRNT 140
#define RST kPRNT
#define J_U 141
#define J_D 142
#define J_L 143
#define J_R 144
#define JUL 145
#define JUR 146
#define JDL 147
#define JDR 148
#define JB0 149
#define JB1 150
#define JB2 151
#define S_D 152
#define S_I 153
#define J_C 154
#define kPAUSE 155
#define BOT kPAUSE
#define kLEFT 8 /* 157 */
#define kRIGHT 21 /* 158 */
#define kUP 11 /* 159 */
#define kDOWN 10 /* 160 */
#define kESC 27 /* 161 */
#define kPGUP 162
#define kHOME 163
#define kPGDN 164
#define kEND 165
#define TIMER_DELAY 30000L
#ifdef PC_JOYSTICK
extern int js_fd;
extern struct JS_DATA_TYPE js;
extern int js_offset_x, js_offset_y;
extern float js_adjustlow_x, js_adjustlow_y, js_adjusthigh_x, js_adjusthigh_y;
extern int c_open_joystick(void);
extern void c_calculate_joystick_parms(void);
extern void c_close_joystick(void);
extern void c_calibrate_joystick(void);
#endif
void c_read_raw_key(int scancode, int pressed);
void c_periodic_update(int dummysig);
void enter_debugger(void);
int c_mygetch(int block);
#endif

977
src/memory.S Normal file
View File

@ -0,0 +1,977 @@
/*
* Apple // emulator for Linux:
* Functions for memory-access indirection table.
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include "apple2.h"
#include "cpu.h"
#include "misc.h"
/* --------------------------------------------------------------------
....................................................................
Apple ][+ Memory documentation (//e differs mostly in softswitches)
I use two jump tables; one for get_memory and one for set_memory
respectively. The jump tables contain exactly 64k entries to
avoid unnecessary range checking. Furthermore, special access
or to serve memory mapped I/O services are easily obtained by
patching the jump table with various routines.
Apple 64k address space:
(Two byte addresses are represented with least significant
byte first, e.g. address FA59 is represented as 59 FA)
Address Description
0000 - 00FF Zero page RAM
0100 - 01FF Stack
0200 - 03EF RAM
03F0 - 03F1 Address for BRK instruction
(normally 59 FA = FA59)
03F2 - 03F3 Soft entry vector (normally BF 9D = 9DBF)
03F4 Power-up byte
03F5 - 03F7 Jump instruction to the subroutine which
handles Applesoft II &-commands
(normally 4C 58 FF = JMP FF58)
03F8 - 03FA Jump instruction to the subroutine which
handles User CTRL-Y commands
(normally 4C 65 FF = JMP FF65)
03FB - 03FD Jump instruction to the subroutine which
handles Non-Maskable Interrupts (NMI)
(normally 4C 65 FF = JMP FF65)
03FE - 03FF Address of the subroutine which handles
Interrupt ReQuests (IRQ)
(normally 65 FF = FF65)
0400 - 07FF Basically primary video text page
0478 - 047F I/O Scratchpad RAM Addresses for Slot 0 - 7
04F8 - 04FF - " " -
0578 - 057F - " " -
05F8 - 05FF - " " -
0678 - 067F - " " -
06F8 - 06FF - " " -
0778 - 077F - " " -
07F8 - 07FF - " " -
----- These two addresses are pretty strange; the values
provided were inconsistent at least on my Apple II
05F8 Holds the slot number of the disk
controller card from which DOS was
booted.
07F8 Holds the slot number (CX, X = Slot #)
of the slot that is currently active.
0800 - 0BFF Basically secondary video text page
0C00 - 1FFF Plain RAM
2000 - 3FFF Primary video hires page (RAM)
4000 - 5FFF Secondary video Hi-Res page (RAM)
6000 - BFFF Plain RAM
(Normally the operating system is
loaded into ~= 9C00 - BFFF)
C000 - C00F Keyboard data
(C00X contains the character ASCII
code of the pressed key. The
value is available at any C00X
address)
C010 - C01F Clear Keyboard strobe
C020 - C02F Cassette output toggle
C030 - C03F Speaker toggle
C040 - C04F Utility strobe
C050 Set graphics mode
C051 Set text mode
C052 Set all text or graphics
C053 Mix text and graphics
C054 Display primary page
C055 Display secondary page
C056 Display low-res graphics
C057 Display hi-res graphics
C058 - C05F Annunciator outputs
C060 Cassette input
C061 - C063 Pushbutton inputs (button 1, 2 and 3)
C064 - C067 Game controller inputs
C068 - C06F Same as C060 - C067
C070 - C07F Game controller strobe
C080 - C08F Slot 0 I/O space (usually a language card)
--- If language card
C080 Reset language card
Read mode enabled
Write mode disabled
Read from language card
Write to ROM (impossible of course)
C081 --- First access
Read mode disabled
Read from ROM
--- On second access
Write mode enabled
Write to language card
C082 --- (Disable language card)
Read mode disabled
Write mode disabled
Read from ROM
Write to ROM
C083 --- First access
Read mode enabled
Read from language card
--- On second access
Write mode enabled
Write to language card
C088 - C08B Same as C080 - C083, but
switch to second bank, i.e.
map addresses D000-DFFF to
other 4k area.
C100 - C1FF Slot 1 PROM
C200 - C2FF Slot 2 PROM
C300 - C3FF Slot 3 PROM
C400 - C4FF Slot 4 PROM
C500 - C5FF Slot 5 PROM
C600 - C6FF Slot 6 PROM
C700 - C7FF Slot 7 PROM
C800 - CFFF Expansion ROM (for peripheral cards)
CFFF Disable access to expansion ROM for
ALL peripheral cards.
D000 - DFFF ROM or 4k RAM if language card is
enabled. However, there are TWO 4k
banks that can be mapped onto addresses
D000 - DFFF. See C088 - C08B.
E000 - FFFF ROM or 8k RAM if language card is
enabled.
----------------------------------------------------------------- */
.comm SN(softswitches),4
.comm SN(base_ramrd),4
.comm SN(base_ramwrt),4
.comm SN(base_textrd),4
.comm SN(base_textwrt),4
.comm SN(base_hgrrd),4
.comm SN(base_hgrwrt),4
.comm SN(base_stackzp),4
.comm SN(base_d000_rd),4
.comm SN(base_d000_wrt),4
.comm SN(base_e000_rd),4
.comm SN(base_e000_wrt),4
.comm SN(base_cxrom),4
.comm SN(base_c3rom),4
/* ram_nop, read_ram_default, write_ram_default: default ram/rom
read/write functions. */
E(ram_nop)
ret
E(read_unmapped_softswitch)
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
ret
E(write_unmapped_softswitch)
ret
E(read_keyboard)
movb SN(apple_ii_64k)+0xC000, %al
ret
E(read_keyboard_strobe)
andb $0x7f, SN(apple_ii_64k)+0xC000
andb $0x7f, SN(apple_ii_64k)+0x1C000
movb SN(apple_ii_64k)+0xC000, %al /* HACK: necessary? */
ret
E(read_random)
pushal
call SN(c_read_random)
popal
movb SN(random_value), %al
ret
E(read_speaker_toggle_pc)
inb $0x61, %al
xorb $0x2, %al
outb %al, $0x61
ret
E(read_switch_primary_page)
testl $SS_PAGE2, SN(softswitches)
jnz _read_switch_primary
ret
_read_switch_primary:
andl $~(SS_PAGE2|SS_SCREEN), SN(softswitches)
pushal
pushl $0
call SN(video_setpage)
addl $4, %esp
popal
ret
E(read_switch_secondary_page)
testl $SS_PAGE2, SN(softswitches)
jz _read_switch_secondary
ret
_read_switch_secondary:
orl $(SS_PAGE2|SS_SCREEN), SN(softswitches)
pushal
pushl $1
call SN(video_setpage)
addl $4, %esp
popal
ret
#ifdef APPLE_IIE
/* PAGE2 off. if 80STORE on then we use main text page1, and if HIRES
on we also use main hires page1, regardless of RAMRD and
RAMWRT. */
E(iie_page2_off)
testl $SS_PAGE2, SN(softswitches) # already off?
jz ram_nop
andl $~(SS_PAGE2|SS_SCREEN), SN(softswitches)
testl $SS_80STORE, SN(softswitches)
jz _iie_page2_off_hires_off # no 80STORE
andl $~(SS_TEXTRD|SS_TEXTWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_textrd)
movl $SN(apple_ii_64k), SN(base_textwrt)
testl $SS_HIRES, SN(softswitches)
jz _iie_page2_off_hires_off # no HIRES
andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrrd)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
_iie_page2_off_hires_off:
pushal
pushl $0 # page 1 main
call SN(video_setpage)
addl $4, %esp
popal
/* call SN(video_redraw)# redraw */
ret
/* PAGE2 on. if 80STORE on then we use aux text page 1, and if HIRES
on we also use aux hires page 1, regardless of RAMRD and
RAMWRT. */
E(iie_page2_on)
testl $SS_PAGE2, SN(softswitches) # already on?
jnz ram_nop
orl $SS_PAGE2, SN(softswitches)
testl $SS_80STORE, SN(softswitches)
jz _iie_page2_on_80store_off # no 80STORE
orl $(SS_TEXTRD|SS_TEXTWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_textrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt)
testl $(SS_HIRES), SN(softswitches)
jz _iie_page2_on_cont
orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
_iie_page2_on_cont:
ret
_iie_page2_on_80store_off: # no 80STORE
orl $SS_SCREEN, SN(softswitches)
pushal
pushl $1 # page 2 main
call SN(video_setpage)
addl $4, %esp
popal
/* call SN(video_redraw)# redraw */
ret
#endif
E(read_switch_graphics)
testl $SS_TEXT, SN(softswitches)
jz ram_nop
andl $~SS_TEXT, SN(softswitches)
call SN(video_redraw)
ret
E(read_switch_text)
testl $SS_TEXT, SN(softswitches)
jnz ram_nop
orl $SS_TEXT, SN(softswitches)
call SN(video_redraw)
ret
E(read_switch_no_mixed)
testl $SS_MIXED, SN(softswitches)
jz ram_nop
andl $~SS_MIXED, SN(softswitches)
call SN(video_redraw)
ret
E(read_switch_mixed)
testl $SS_MIXED, SN(softswitches)
jnz ram_nop
orl $SS_MIXED, SN(softswitches)
call SN(video_redraw)
ret
E(read_switch_lores)
testl $SS_HIRES, SN(softswitches)
jz ram_nop
andl $~SS_HIRES, SN(softswitches)
call SN(video_redraw)
ret
E(read_switch_hires)
testl $SS_HIRES, SN(softswitches)
jnz ram_nop
orl $SS_HIRES, SN(softswitches)
call SN(video_redraw)
ret
#ifdef APPLE_IIE
/* HIRES off. use RAMRD/RAMWRT offsets for hires page 1. */
E(iie_hires_off)
testl $SS_HIRES, SN(softswitches) # already off?
jz ram_nop
andl $~(SS_HIRES|SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrrd)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
testl $SS_RAMRD,SN(softswitches)
jz iie_hires_off_no_ramrd
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
orl $SS_HGRRD, SN(softswitches)
iie_hires_off_no_ramrd:
testl $SS_RAMWRT,SN(softswitches)
jz iie_hires_off_no_ramwrt
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
orl $SS_HGRWRT, SN(softswitches)
iie_hires_off_no_ramwrt:
call SN(video_redraw) # update screen
ret
/* HIRES on. if 80STORE on, use PAGE2 offset for hires page 1. */
E(iie_hires_on)
testl $SS_HIRES, SN(softswitches) # already on?
jnz ram_nop
orl $SS_HIRES, SN(softswitches) # hires on
testl $SS_80STORE, SN(softswitches)
jz iie_hires_on_80store_off # no 80STORE
testl $SS_PAGE2, SN(softswitches)
jz iie_hires_on_80store_aux
andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrrd)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
jmp iie_hires_on_80store_off
iie_hires_on_80store_aux:
orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
iie_hires_on_80store_off:
call SN(video_redraw) # update screen
ret
#endif
/*****************************************************************************/
.comm joy_trigger0, 2
.comm joy_trigger1, 2
.comm joy_trigger2, 2
.comm joy_trigger3, 2
E(read_button0)
movb SN(joy_button0), %al
ret
E(read_button1)
movb SN(joy_button1), %al
ret
E(read_button2)
movb SN(joy_button2), %al
ret
E(read_gc0)
cmpw $0xFF, joy_trigger0
je read_gc0_cont
incw joy_trigger0
read_gc0_cont:
movw joy_trigger0, %ax
cmpw %ax, SN(joy_x)
jge read_gc0_ff /* XXXX is this correct? */
movb $0, %al
ret
read_gc0_ff:
movb $0xFF, %al
ret
E(read_gc1)
cmpw $0xFF, joy_trigger1
je read_gc1_cont
incw joy_trigger1
read_gc1_cont:
movw joy_trigger1, %ax
cmpw %ax, SN(joy_y)
jge read_gc1_ff
movb $0, %al
ret
read_gc1_ff:
movb $0xFF, %al
ret
/* HACK not doing anything... */
E(iie_read_gc2)
ret
E(iie_read_gc3)
ret
E(read_gc_strobe)
movb $0, joy_trigger0
movb $0, joy_trigger1
movb $0, joy_trigger2
movb $0, joy_trigger3
ret
E(iie_c080)
testl $SS_ALTZP, SN(softswitches)
jz lc_c080
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c080: read RAM; no write; use $D000 bank 2. */
E(lc_c080)
orl $SS_LCRAM|SS_BANK2, SN(softswitches)
andl $~(SS_LCSEC|SS_LCWRT), SN(softswitches)
movl $SN(language_banks)-0xD000, SN(base_d000_rd)
movl $SN(language_card)-0xE000, SN(base_e000_rd)
movl $0, SN(base_d000_wrt)
movl $0, SN(base_e000_wrt)
ret
E(iie_c081)
testl $SS_ALTZP, SN(softswitches)
jz lc_c081
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c081: read ROM; write RAM; use $D000 bank 2. */
E(lc_c081)
testl $SS_LCSEC, SN(softswitches)
je lc_c081_exit
orl $SS_LCWRT, SN(softswitches)
movl $SN(language_banks)-0xD000, SN(base_d000_wrt)
movl $SN(language_card)-0xE000, SN(base_e000_wrt)
lc_c081_exit:
andl $~SS_LCRAM, SN(softswitches)
orl $SS_LCSEC|SS_BANK2, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_d000_rd)
movl $SN(apple_ii_64k), SN(base_e000_rd)
ret
/* There is no iie_c082 --- since the LC is offline, no auxillary memory
* could be exposed. (ditto for c08a) */
/* c082: read ROM; no write; use $D000 bank 2. */
E(lc_c082)
andl $~(SS_LCRAM|SS_LCWRT|SS_LCSEC), SN(softswitches)
orl $SS_BANK2, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_d000_rd)
movl $SN(apple_ii_64k), SN(base_e000_rd)
movl $0, SN(base_d000_wrt)
movl $0, SN(base_e000_wrt)
ret
E(iie_c083)
testl $SS_ALTZP, SN(softswitches)
jz lc_c083
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c083: read and write RAM; no write; use $D000 bank 2. */
E(lc_c083) testl $SS_LCSEC, SN(softswitches)
je lc_c083_exit
orl $SS_LCWRT, SN(softswitches)
movl $SN(language_banks)-0xD000, SN(base_d000_wrt)
movl $SN(language_card)-0xE000, SN(base_e000_wrt)
lc_c083_exit:
orl $(SS_LCSEC|SS_LCRAM|SS_BANK2), SN(softswitches)
movl $SN(language_banks)-0xD000, SN(base_d000_rd)
movl $SN(language_card)-0xE000, SN(base_e000_rd)
ret
E(iie_c088)
testl $SS_ALTZP, SN(softswitches)
jz lc_c088
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c088: read RAM; no write; use $D000 bank 1. */
E(lc_c088)
orl $(SS_LCRAM), SN(softswitches)
andl $~(SS_LCWRT|SS_LCSEC|SS_BANK2), SN(softswitches)
movl $SN(language_banks)-0xC000, SN(base_d000_rd)
movl $SN(language_card)-0xE000, SN(base_e000_rd)
movl $0, SN(base_d000_wrt)
movl $0, SN(base_e000_wrt)
ret
E(iie_c089)
testl $SS_ALTZP, SN(softswitches)
jz lc_c089
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c089: read ROM; write RAM; use $D000 bank 1. */
E(lc_c089)
testl $SS_LCSEC, SN(softswitches)
jz lc_c089_exit
orl $SS_LCWRT, SN(softswitches)
movl $SN(language_banks)-0xC000, SN(base_d000_wrt)
movl $SN(language_card)-0xE000, SN(base_e000_wrt)
lc_c089_exit:
andl $~(SS_LCRAM|SS_BANK2), SN(softswitches)
orl $(SS_LCSEC), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_d000_rd)
movl $SN(apple_ii_64k), SN(base_e000_rd)
ret
/* there is no iie_c08a */
/* c08a: read ROM; no write; use $D000 bank 1. */
E(lc_c08a)
andl $~(SS_LCRAM|SS_LCWRT|SS_LCSEC|SS_BANK2), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_d000_rd)
movl $SN(apple_ii_64k), SN(base_e000_rd)
movl $0, SN(base_d000_wrt)
movl $0, SN(base_e000_wrt)
ret
E(iie_c08b)
testl $SS_ALTZP, SN(softswitches)
jz lc_c08b
pushl $lc_to_auxmem /* sneak this code in when
* ][+ routine exits */
/* c08b: read and write RAM; use $D000 bank 1. */
E(lc_c08b)
testl $SS_LCSEC, SN(softswitches)
jz lc_c08b_exit
orl $SS_LCWRT, SN(softswitches)
movl $SN(language_banks)-0xC000, SN(base_d000_wrt)
movl $SN(language_card)-0xE000, SN(base_e000_wrt)
lc_c08b_exit:
orl $(SS_LCRAM|SS_LCSEC), SN(softswitches)
andl $~SS_BANK2,SN(softswitches)
movl $SN(language_banks)-0xC000, SN(base_d000_rd)
movl $SN(language_card)-0xE000, SN(base_e000_rd)
ret
/* -------------------------------------------------------------------------
* misc //e functions
* ------------------------------------------------------------------------- */
#ifdef APPLE_IIE
/* 80STORE off. use RAMRD/RAMWRT for text/hires display page 1 */
E(iie_80store_off)
testl $SS_80STORE, SN(softswitches) # already off?
jz ram_nop
andl $~(SS_80STORE|SS_TEXTRD|SS_TEXTWRT|SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k),SN(base_textrd)
movl $SN(apple_ii_64k),SN(base_textwrt)
movl $SN(apple_ii_64k),SN(base_hgrrd)
movl $SN(apple_ii_64k),SN(base_hgrwrt)
testl $SS_RAMRD, SN(softswitches)
jz iie_80store_off_noramrd
orl $(SS_TEXTRD|SS_HGRRD),SN(softswitches)
movl $SN(apple_ii_64k)+BANK2,SN(base_textrd)
movl $SN(apple_ii_64k)+BANK2,SN(base_hgrrd)
iie_80store_off_noramrd:
testl $SS_RAMRD, SN(softswitches)
jz iie_80store_off_noramwrt
orl $(SS_TEXTWRT|SS_HGRWRT),SN(softswitches)
movl $SN(apple_ii_64k)+BANK2,SN(base_textwrt)
movl $SN(apple_ii_64k)+BANK2,SN(base_hgrwrt)
iie_80store_off_noramwrt:
testl $SS_PAGE2, SN(softswitches)
jz ram_nop
orl $SS_SCREEN, SN(softswitches)
pushal
pushl $1
call SN(video_setpage)
addl $4, %esp
popal
/* call SN(video_redraw) # redraw */
ret
/* 80STORE on. we use PAGE2 offset to access text page 1. if HIRES on
we also use PAGE2 offset to access hires page 1 */
E(iie_80store_on)
testl $SS_80STORE, SN(softswitches) # already on?
jnz ram_nop
orl $SS_80STORE, SN(softswitches)
testl $SS_PAGE2, SN(softswitches)
jnz iie_80store_on_page2_on
andl $~(SS_TEXTRD|SS_TEXTWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_textrd)
movl $SN(apple_ii_64k), SN(base_textwrt)
testl $SS_HIRES, SN(softswitches)
jz iie_80store_on_cont
andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrrd)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
jmp iie_80store_on_cont
iie_80store_on_page2_on:
orl $(SS_TEXTRD|SS_TEXTWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_textrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt)
testl $SS_HIRES, SN(softswitches)
jz iie_80store_on_cont
orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
iie_80store_on_cont:
andl $~SS_SCREEN, SN(softswitches)
pushal
pushl $0 # page 1
call SN(video_setpage)
addl $4, %esp
popal
/* call SN(video_redraw) # redraw */
ret
return80: movb $0x80,%al
ret
E(iie_check_80store)
testl $SS_80STORE,SN(softswitches)
jnz return80
xorb %al,%al
ret
/* RAMRD main. if 80STORE off then text/hires display pages are in
main memory. */
E(iie_ramrd_main)
testl $SS_RAMRD, SN(softswitches) # already off?
jz ram_nop
andl $~SS_RAMRD, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_ramrd)
testl $SS_80STORE, SN(softswitches) # 80store?
jnz iie_ramrd_main_80store_on
andl $~(SS_TEXTRD|SS_HGRRD), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_textrd)
movl $SN(apple_ii_64k), SN(base_hgrrd)
/* call SN(video_redraw) # redraw */
ret
iie_ramrd_main_80store_on:
testl $SS_HIRES, SN(softswitches)
jnz ram_nop
andl $~SS_HGRRD, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrrd)
/* call SN(video_redraw) # redraw */
ret
/* RAMRD aux. if 80STORE off then text/hires display pages are in aux
memory. */
E(iie_ramrd_aux)
testl $SS_RAMRD, SN(softswitches) # already on?
jnz ram_nop
orl $SS_RAMRD, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_ramrd)
testl $SS_80STORE, SN(softswitches) # 80store?
jnz iie_ramrd_aux_80store_on
orl $(SS_TEXTRD|SS_HGRRD), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_textrd)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
/* call SN(video_redraw) # redraw */
ret
iie_ramrd_aux_80store_on:
testl $SS_HIRES, SN(softswitches)
jnz ram_nop # already set
orl $(SS_HGRRD), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd)
/* call SN(video_redraw) # redraw */
ret
E(iie_check_ramrd)
testl $SS_RAMRD, SN(softswitches)
jnz return80
xorb %al,%al
ret
/* RAMWRT main. if 80STORE off then text/hires display pages are in
main memory. */
E(iie_ramwrt_main)
testl $SS_RAMWRT, SN(softswitches) # already off?
jz ram_nop
andl $~SS_RAMWRT, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_ramwrt) # main RAM
testl $SS_80STORE, SN(softswitches) # 80store?
jnz iie_ramwrt_main_80store_on
andl $~(SS_TEXTWRT|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k), SN(base_textwrt)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
/* call SN(video_redraw) # redraw */
ret
iie_ramwrt_main_80store_on:
testl $SS_HIRES, SN(softswitches)
jnz ram_nop
andl $~SS_HGRWRT, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_hgrwrt)
/* call SN(video_redraw) # redraw */
ret
/* RAMWRT aux. if 80STORE off then write to text/hires display pages
are in aux memory. */
E(iie_ramwrt_aux)
testl $SS_RAMWRT, SN(softswitches) # already on?
jnz ram_nop
orl $SS_RAMWRT, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_ramwrt) # aux RAM
testl $SS_80STORE, SN(softswitches) # 80store?
jnz iie_ramwrt_aux_80store_on
orl $(SS_TEXTWRT|SS_HGRWRT), SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
/* call SN(video_redraw) # redraw */
ret
iie_ramwrt_aux_80store_on:
testl $SS_HIRES, SN(softswitches)
jnz ram_nop
orl $SS_HGRWRT, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt)
/* call SN(video_redraw) # redraw */
ret
E(iie_check_ramwrt)
testl $SS_RAMWRT, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_altzp_main)
testl $SS_ALTZP, SN(softswitches)
jz 1f /* test if ALTZP already off -
* due to d000-bank issues it is
* *needed*, not just a shortcut */
andl $~SS_ALTZP, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_stackzp)
andl $0xFFFF, SP_Reg
testl $SS_LCRAM|SS_LCWRT, SN(softswitches)
jz 1f /* shortest path for common case */
testl $SS_LCRAM, SN(softswitches)
jz 2f
subl $0x2000, SN(base_d000_rd)
movl $SN(language_card)-0xE000, SN(base_e000_rd)
2: testl $SS_LCWRT, SN(softswitches)
jz 1f
subl $0x2000, SN(base_d000_wrt)
movl $SN(language_card)-0xE000, SN(base_e000_wrt)
1: ret
E(iie_altzp_aux)
testl $SS_ALTZP, SN(softswitches)
jnz 1f /* test if ALTZP already on -
* due to d000-bank issues it is
* *needed*, not just a shortcut */
orl $SS_ALTZP, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_stackzp)
orl $BANK2, SP_Reg
testl $SS_LCRAM|SS_LCWRT, SN(softswitches)
jz 1f /* shortest path for common case */
lc_to_auxmem: /* called by lc routines */
testl $SS_LCRAM, SN(softswitches)
jz 2f
addl $0x2000, SN(base_d000_rd)
movl $SN(language_card)-0xC000, SN(base_e000_rd)
2: testl $SS_LCWRT, SN(softswitches)
jz 1f
addl $0x2000, SN(base_d000_wrt)
movl $SN(language_card)-0xC000, SN(base_e000_wrt)
1: ret
E(iie_check_altzp)
testl $SS_ALTZP, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_80col_off)
testl $SS_80COL, SN(softswitches)
jz ram_nop
andl $~SS_80COL, SN(softswitches)
testl $(SS_TEXT|SS_MIXED|SS_DHIRES), SN(softswitches)
jnz SN(video_redraw)
ret
E(iie_80col_on)
testl $SS_80COL, SN(softswitches)
jnz ram_nop
orl $SS_80COL, SN(softswitches)
testl $(SS_TEXT|SS_MIXED|SS_DHIRES), SN(softswitches)
jnz SN(video_redraw)
ret
E(iie_check_80col)
testl $SS_80COL, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_altchar_off)
testl $SS_ALTCHAR, SN(softswitches)
jz ram_nop
andl $~SS_ALTCHAR, SN(softswitches)
pushal
call SN(c_set_primary_char)
popal
ret
E(iie_altchar_on)
testl $SS_ALTCHAR, SN(softswitches)
jnz ram_nop
orl $SS_ALTCHAR, SN(softswitches)
pushal
call SN(c_set_altchar)
popal
ret
E(iie_check_altchar)
testl $SS_ALTCHAR, SN(softswitches)
jnz return80
xorb %al, %al
ret
/* unset ioudis flag and read_gc_strobe */
E(iie_ioudis_off)
andl $~SS_IOUDIS, SN(softswitches)
jmp SN(read_gc_strobe)
/* set ioudis flag and read_gc_strobe */
E(iie_ioudis_on)
orl $SS_IOUDIS, SN(softswitches)
jmp SN(read_gc_strobe)
/* check ioudis flag and read_gc_strobe */
E(iie_check_ioudis)
call SN(read_gc_strobe)
testl $SS_IOUDIS, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_dhires_on)
testl $SS_IOUDIS, SN(softswitches)
jz ram_nop
orl $SS_DHIRES, SN(softswitches)
call SN(video_redraw)
ret
E(iie_dhires_off)
testl $SS_IOUDIS, SN(softswitches)
jz ram_nop
andl $~SS_DHIRES, SN(softswitches)
call SN(video_redraw)
ret
/* check dhires flag and read_gc_strobe */
E(iie_check_dhires)
call SN(read_gc_strobe)
testl $SS_DHIRES, SN(softswitches)
jnz return80
ret
E(iie_check_text)
testl $SS_TEXT, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_check_mixed)
testl $SS_MIXED, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_check_page2)
testl $SS_PAGE2, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_check_hires)
testl $SS_HIRES, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_check_bank)
testl $SS_BANK2, SN(softswitches)
jnz return80
xorb %al, %al
ret
E(iie_check_lcram)
testl $SS_LCRAM, SN(softswitches)
jnz return80
xorb %al, %al
ret
/* HACK not doing anything... */
E(iie_check_vbl)
ret
/* ---------------------------------- */
E(iie_c3rom_peripheral)
andl $~SS_C3ROM, SN(softswitches)
testl $SS_CXROM, SN(softswitches)
jnz 1f /* CXROM-internal preempts C3ROM */
movl $SN(apple_ii_64k), SN(base_c3rom)
1: ret
E(iie_c3rom_internal)
orl $SS_C3ROM, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_c3rom)
ret
E(iie_check_c3rom)
testl $SS_C3ROM, SN(softswitches)
jz return80
xorb %al, %al
ret
E(iie_cxrom_peripheral)
andl $~SS_CXROM, SN(softswitches)
movl $SN(apple_ii_64k), SN(base_cxrom)
testl $SS_C3ROM, SN(softswitches)
jnz 1f
movl $SN(apple_ii_64k), SN(base_c3rom)
1: ret
E(iie_cxrom_internal)
orl $SS_CXROM, SN(softswitches)
movl $SN(apple_ii_64k)+BANK2, SN(base_cxrom)
movl $SN(apple_ii_64k)+BANK2, SN(base_c3rom)
ret
E(iie_check_cxrom)
testl $SS_CXROM, SN(softswitches)
jnz return80
xorb %al, %al
ret
/* HACK!!!!! - how does the expansion slot get referenced? need to handle other roms requesting to use this area!!!! */
E(iie_read_slot_expansion)
orl SN(c8rom_offset), EffectiveAddr_E
movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al
andl $0xFFFF, EffectiveAddr_E
ret
/* HACK!!!!! - how does the expansion slot get referenced? */
E(iie_disable_slot_expansion)
ret
#endif /* APPLE_IIE */

745
src/misc.c Normal file
View File

@ -0,0 +1,745 @@
/*
* Apple // emulator for Linux: Miscellaneous support
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include "misc.h"
#include "video.h"
#include "disk.h"
#include "interface.h"
#include "keys.h"
#ifdef DEBUGGER
#include "debug.h"
#endif
#include "cpu.h"
#include "glue.h"
#include "prefs.h"
const struct itimerval timer_off = {{0,0},{0,0}};
const struct itimerval timer_on = {{0,TIMER_DELAY},{0,TIMER_DELAY}};
/* ----------------------------------
internal apple2 variables
---------------------------------- */
static unsigned char apple_ii_rom[12288];
#ifdef APPLE_IIE
static unsigned char apple_iie_rom[32768]; /* //e */
#endif
#ifdef DEBUGGER
/* in debugger.c */
extern int breakpoints[];
extern int watchpoints[];
extern int op_breakpoints[256];
#endif
GLUE_FIXED_READ(read_ram_default,apple_ii_64k)
GLUE_FIXED_WRITE(write_ram_default,apple_ii_64k)
GLUE_BANK_READ(read_ram_bank,base_d000_rd)
GLUE_BANK_MAYBEWRITE(write_ram_bank,base_d000_wrt)
GLUE_BANK_READ(read_ram_lc,base_e000_rd)
GLUE_BANK_MAYBEWRITE(write_ram_lc,base_e000_wrt)
#ifdef APPLE_IIE
GLUE_BANK_READ(iie_read_ram_default,base_ramrd)
GLUE_BANK_WRITE(iie_write_ram_default,base_ramwrt)
GLUE_BANK_READ(iie_read_ram_text_page0,base_textrd)
GLUE_BANK_WRITE(iie_write_screen_hole_text_page0,base_textwrt)
GLUE_BANK_READ(iie_read_ram_hires_page0,base_hgrrd)
GLUE_BANK_WRITE(iie_write_screen_hole_hires_page0,base_hgrwrt)
GLUE_BANK_READ(iie_read_ram_zpage_and_stack,base_stackzp)
GLUE_BANK_WRITE(iie_write_ram_zpage_and_stack,base_stackzp)
GLUE_BANK_READ(iie_read_slot3,base_c3rom)
GLUE_BANK_READ(iie_read_slotx,base_cxrom)
/* -------------------------------------------------------------------------
c_set_altchar() - set alternate character set
------------------------------------------------------------------------- */
void c_set_altchar()
{
video_loadfont(0x40,0x20,mousetext_glyphs,1);
video_loadfont(0x60,0x20,lcase_glyphs,2);
video_redraw();
}
/* -------------------------------------------------------------------------
c_set_primary_char() - set primary character set
------------------------------------------------------------------------- */
void c_set_primary_char()
{
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_redraw();
}
#endif/* APPLE_IIE */
/* -------------------------------------------------------------------------
c_initialize_font(): Initialize ROM character table to primary char set
------------------------------------------------------------------------- */
void c_initialize_font()
{
video_loadfont(0x00,0x40,ucase_glyphs,2);
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_loadfont(0x80,0x40,ucase_glyphs,0);
video_loadfont(0xC0,0x20,ucase_glyphs,0);
video_loadfont(0xE0,0x20,lcase_glyphs,0);
video_redraw();
}
/* -------------------------------------------------------------------------
c_initialize_tables()
------------------------------------------------------------------------- */
void c_initialize_tables() {
int i;
pre_compact(); /* Prepare for VM compression */
/* reset everything */
for (i = 0; i < 0x10000; i++) {
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[i].r = iie_read_ram_default;
cpu65_vmem[i].w = iie_write_ram_default;
} else
#endif
{
cpu65_vmem[i].r = read_ram_default;
cpu65_vmem[i].w = write_ram_default;
}
}
/* language card read/write area */
for (i = 0xD000; i < 0xE000; i++) {
{
cpu65_vmem[i].w =
write_ram_bank;
cpu65_vmem[i].r =
read_ram_bank;
}
}
for (i = 0xE000; i < 0x10000; i++) {
{
cpu65_vmem[i].w =
write_ram_lc;
cpu65_vmem[i].r =
read_ram_lc;
}
}
/* done common initialization */
#ifdef APPLE_IIE
/* initialize zero-page, //e specific */
if (apple_mode == IIE_MODE) {
for (i = 0; i < 0x200; i++) {
cpu65_vmem[i].r =
iie_read_ram_zpage_and_stack;
cpu65_vmem[i].w =
iie_write_ram_zpage_and_stack;
}
}
#endif
#ifdef APPLE_IIE
/* initialize first text & hires page, which are specially bank switched
*
* video_set() substitutes it's own hooks for all visible write locations
* affect the display, leaving our write-functions in place only at the
* `screen holes', hence the name.
*/
for (i = 0x400; i < 0x800; i++) {
cpu65_vmem[i].r =
iie_read_ram_text_page0;
cpu65_vmem[i].w =
iie_write_screen_hole_text_page0;
}
for (i = 0x2000; i < 0x4000; i++) {
cpu65_vmem[i].r =
iie_read_ram_hires_page0;
cpu65_vmem[i].w =
iie_write_screen_hole_hires_page0;
}
#endif
/* softswich rom */
for (i = 0xC000; i < 0xC100; i++) {
cpu65_vmem[i].r =
read_unmapped_softswitch;
cpu65_vmem[i].w =
write_unmapped_softswitch;
}
/* slot rom */
for (i = 0xC100; i < 0xD000; i++) {
cpu65_vmem[i].r =
#ifdef APPLE_IIE
iie_read_ram_default;
#else
read_ram_default;
#endif
cpu65_vmem[i].w =
ram_nop;
}
/* keyboard data and strobe (READ) */
for (i = 0xC000; i < 0xC010; i++) {
cpu65_vmem[i].r =
read_keyboard;
}
for (i = 0xC010; i < 0xC020; i++) {
cpu65_vmem[i].r =
cpu65_vmem[i].w =
read_keyboard_strobe;
}
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
/* RDBNK2 switch */
cpu65_vmem[0xC011].r =
iie_check_bank;
/* RDLCRAM switch */
cpu65_vmem[0xC012].r =
iie_check_lcram;
/* 80STORE switch */
cpu65_vmem[0xC000].w = iie_80store_off;
cpu65_vmem[0xC001].w = iie_80store_on;
cpu65_vmem[0xC018].r = iie_check_80store;
/* RAMRD switch */
cpu65_vmem[0xC002].w = iie_ramrd_main;
cpu65_vmem[0xC003].w = iie_ramrd_aux;
cpu65_vmem[0xC013].r = iie_check_ramrd;
/* RAMWRT switch */
cpu65_vmem[0xC004].w = iie_ramwrt_main;
cpu65_vmem[0xC005].w = iie_ramwrt_aux;
cpu65_vmem[0xC014].r = iie_check_ramwrt;
/* ALTZP switch */
cpu65_vmem[0xC008].w = iie_altzp_main;
cpu65_vmem[0xC009].w = iie_altzp_aux;
cpu65_vmem[0xC016].r = iie_check_altzp;
/* 80COL switch */
cpu65_vmem[0xC00C].w = iie_80col_off;
cpu65_vmem[0xC00D].w = iie_80col_on;
cpu65_vmem[0xC01F].r = iie_check_80col;
/* ALTCHAR switch */
cpu65_vmem[0xC00E].w = iie_altchar_off;
cpu65_vmem[0xC00F].w = iie_altchar_on;
cpu65_vmem[0xC01E].r = iie_check_altchar;
/* SLOTC3ROM switch */
cpu65_vmem[0xC00A].w = iie_c3rom_internal;
cpu65_vmem[0xC00B].w = iie_c3rom_peripheral;
cpu65_vmem[0xC017].r = iie_check_c3rom;
/* SLOTCXROM switch */
cpu65_vmem[0xC006].w = iie_cxrom_peripheral;
cpu65_vmem[0xC007].w = iie_cxrom_internal;
cpu65_vmem[0xC015].r = iie_check_cxrom;
/* RDVBLBAR switch */
cpu65_vmem[0xC019].r =
iie_check_vbl;
}
#endif
/* random number generator */
for (i = 0xC020; i < 0xC030; i++)
cpu65_vmem[i].r =
cpu65_vmem[i].w =
read_random;
/* TEXT switch */
cpu65_vmem[0xC050].r =
cpu65_vmem[0xC050].w =
read_switch_graphics;
cpu65_vmem[0xC051].r =
cpu65_vmem[0xC051].w =
read_switch_text;
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC01A].r =
iie_check_text;
}
#endif
/* MIXED switch */
cpu65_vmem[0xC052].r =
cpu65_vmem[0xC052].w =
read_switch_no_mixed;
cpu65_vmem[0xC053].r =
cpu65_vmem[0xC053].w =
read_switch_mixed;
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC01B].r =
iie_check_mixed;
}
/* PAGE2 switch */
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC054].r =
cpu65_vmem[0xC054].w =
iie_page2_off;
} else
#endif
{
cpu65_vmem[0xC054].r =
cpu65_vmem[0xC054].w =
read_switch_primary_page;
}
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC01C].r =
iie_check_page2;
}
/* PAGE2 switch */
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC055].r =
cpu65_vmem[0xC055].w =
iie_page2_on;
} else
#endif
{
cpu65_vmem[0xC055].r =
cpu65_vmem[0xC055].w =
read_switch_secondary_page;
}
/* HIRES switch */
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC01D].r =
iie_check_hires;
cpu65_vmem[0xC056].r =
cpu65_vmem[0xC056].w =
iie_hires_off;
cpu65_vmem[0xC057].r =
cpu65_vmem[0xC057].w =
iie_hires_on;
}
else
#endif
{
cpu65_vmem[0xC056].r =
cpu65_vmem[0xC056].w =
read_switch_lores;
cpu65_vmem[0xC057].r =
cpu65_vmem[0xC057].w =
read_switch_hires;
}
/* game I/O switches */
cpu65_vmem[0xC061].r =
cpu65_vmem[0xC069].r =
read_button0;
cpu65_vmem[0xC062].r =
cpu65_vmem[0xC06A].r =
read_button1;
cpu65_vmem[0xC063].r =
cpu65_vmem[0xC06B].r =
read_button2;
cpu65_vmem[0xC064].r =
cpu65_vmem[0xC06C].r =
read_gc0;
cpu65_vmem[0xC065].r =
cpu65_vmem[0xC06D].r =
read_gc1;
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[0xC066].r =
iie_read_gc2;
cpu65_vmem[0xC067].r =
iie_read_gc3;
}
#endif
for (i = 0xC070; i < 0xC080; i++)
cpu65_vmem[i].r =
cpu65_vmem[i].w =
read_gc_strobe;
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
/* IOUDIS switch & read_gc_strobe */
cpu65_vmem[0xC07E].w =
iie_ioudis_on;
cpu65_vmem[0xC07F].w =
iie_ioudis_off;
cpu65_vmem[0xC07E].r =
iie_check_ioudis;
cpu65_vmem[0xC07F].r =
iie_check_dhires;
/* DHIRES/Annunciator switches */
cpu65_vmem[0xC05E].w =
cpu65_vmem[0xC05E].r =
iie_dhires_on;
cpu65_vmem[0xC05F].w =
cpu65_vmem[0xC05F].r =
iie_dhires_off;
}
#endif
#ifdef APPLE_IIE
/* language card softswitches */
cpu65_vmem[0xC080].r = cpu65_vmem[0xC080].w =
cpu65_vmem[0xC084].r = cpu65_vmem[0xC084].w =
(apple_mode == IIE_MODE) ? iie_c080 : lc_c080;
cpu65_vmem[0xC081].r = cpu65_vmem[0xC081].w =
cpu65_vmem[0xC085].r = cpu65_vmem[0xC085].w =
(apple_mode == IIE_MODE) ? iie_c081 : lc_c081;
cpu65_vmem[0xC082].r = cpu65_vmem[0xC082].w =
cpu65_vmem[0xC086].r = cpu65_vmem[0xC086].w =
lc_c082;
cpu65_vmem[0xC083].r = cpu65_vmem[0xC083].w =
cpu65_vmem[0xC087].r = cpu65_vmem[0xC087].w =
(apple_mode == IIE_MODE) ? iie_c083 : lc_c083;
cpu65_vmem[0xC088].r = cpu65_vmem[0xC088].w =
cpu65_vmem[0xC08C].r = cpu65_vmem[0xC08C].w =
(apple_mode == IIE_MODE) ? iie_c088 : lc_c088;
cpu65_vmem[0xC089].r = cpu65_vmem[0xC089].w =
cpu65_vmem[0xC08D].r = cpu65_vmem[0xC08D].w =
(apple_mode == IIE_MODE) ? iie_c089 : lc_c089;
cpu65_vmem[0xC08A].r = cpu65_vmem[0xC08A].w =
cpu65_vmem[0xC08E].r = cpu65_vmem[0xC08E].w =
lc_c08a;
cpu65_vmem[0xC08B].r = cpu65_vmem[0xC08B].w =
cpu65_vmem[0xC08F].r = cpu65_vmem[0xC08F].w =
(apple_mode == IIE_MODE) ? iie_c08b : lc_c08b;
#else /* !APPLE_IIE */
/* language card softswitches */
cpu65_vmem[0xC080].r = cpu65_vmem[0xC080].w =
cpu65_vmem[0xC084].r = cpu65_vmem[0xC084].w =
lc_c080;
cpu65_vmem[0xC081].r = cpu65_vmem[0xC081].w =
cpu65_vmem[0xC085].r = cpu65_vmem[0xC085].w =
lc_c081;
cpu65_vmem[0xC082].r = cpu65_vmem[0xC082].w =
cpu65_vmem[0xC086].r = cpu65_vmem[0xC086].w =
lc_c082;
cpu65_vmem[0xC083].r = cpu65_vmem[0xC083].w =
cpu65_vmem[0xC087].r = cpu65_vmem[0xC087].w =
lc_c083;
cpu65_vmem[0xC088].r = cpu65_vmem[0xC088].w =
cpu65_vmem[0xC08C].r = cpu65_vmem[0xC08C].w =
lc_c088;
cpu65_vmem[0xC089].r = cpu65_vmem[0xC089].w =
cpu65_vmem[0xC08D].r = cpu65_vmem[0xC08D].w =
lc_c089;
cpu65_vmem[0xC08A].r = cpu65_vmem[0xC08A].w =
cpu65_vmem[0xC08E].r = cpu65_vmem[0xC08E].w =
lc_c08a;
cpu65_vmem[0xC08B].r = cpu65_vmem[0xC08B].w =
cpu65_vmem[0xC08F].r = cpu65_vmem[0xC08F].w =
lc_c08b;
#endif /* !APPLE_IIE */
#ifdef APPLE_IIE
/* slot i/o area */
for (i = 0xC100; i < 0xC300; i++) {
cpu65_vmem[i].r =
iie_read_slotx; /* slots 1 & 2 (x) */
}
for (i = 0xC300; i < 0xC400; i++) {
cpu65_vmem[i].r =
iie_read_slot3; /* slot 3 (80col) */
}
for (i = 0xC400; i < 0xC800; i++) {
cpu65_vmem[i].r =
iie_read_slotx; /* slots 4 - 7 (x) */
}
for (i = 0xC800; i < 0xD000; i++) {
cpu65_vmem[i].r =
iie_read_slot_expansion; /* expansion rom */
}
cpu65_vmem[0xCFFF].r =
cpu65_vmem[0xCFFF].w =
iie_disable_slot_expansion;
#endif
video_set(0); /* must be done here, between pre_compact & compact */
disk_install(6); /* Put a Disk ][ Controller in slot 6 */
compact(); /* Compress memory so that identical pages share storage */
}
/* -------------------------------------------------------------------------
c_initialize_apple_ii_memory()
------------------------------------------------------------------------- */
void c_initialize_apple_ii_memory()
{
FILE *f;
int i;
static int ii_rom_loaded = 0;
#ifdef APPLE_IIE
static int iie_rom_loaded = 0;
#endif
for (i = 0; i < 0x10000; i++) {
apple_ii_64k[0][i] = 0;
apple_ii_64k[1][i] = 0;
}
for (i = 0; i < 8192; i++)
language_card[0][i] = language_card[1][i] = 0;
for (i = 0; i < 8192; i++)
language_banks[0][i] = language_banks[1][i] = 0;
if (!ii_rom_loaded)
{
snprintf(temp, TEMPSIZE, "%s/apple_II.rom", system_path);
if ((f = fopen(temp, "r")) == NULL) {
printf("OOPS!\n");
printf("Cannot find file '%s'.\n",temp);
exit(0);
}
fread(apple_ii_rom, 0x3000, 1, f);
fclose(f);
ii_rom_loaded = 1;
}
#ifdef APPLE_IIE
if (!iie_rom_loaded) {
snprintf(temp, TEMPSIZE, "%s/apple_IIe.rom", system_path);
if ((f = fopen(temp, "r")) == NULL) {
printf("Cannot find file '%s'.\n",temp);
exit(0);
}
fread(apple_iie_rom, 32768, 1, f);
fclose(f);
iie_rom_loaded = 1;
}
#endif
for (i = 0xD000; i < 0x10000; i++)
apple_ii_64k[0][i] = apple_ii_rom[i - 0xD000];
for (i = 0; i < 0x1000; i++)
language_banks[0][i] = apple_ii_rom[i];
for (i = 0; i < 0x2000; i++)
language_card[0][i] = apple_ii_rom[i + 0x1000];
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
/* load the rom from 0xC000, slot rom main, internal rom aux */
for (i = 0xC000; i < 0x10000; i++) {
apple_ii_64k[0][i] = apple_iie_rom[i - 0xC000];
apple_ii_64k[1][i] = apple_iie_rom[i - 0x8000];
}
for (i = 0; i < 0x1000; i++) {
language_banks[0][i] = apple_iie_rom[i + 0x1000];
language_banks[1][i] = apple_iie_rom[i + 0x5000];
}
for (i = 0; i < 0x2000; i++) {
language_card[0][i] = apple_iie_rom[i + 0x2000];
language_card[1][i] = apple_iie_rom[i + 0x6000];
}
}
else
#endif
/* softswitch memory HACK - why this? */
{
for (i = 0xC100; i < 0xD000; i++) {
apple_ii_64k[0][i] = i & 0xFF;
apple_ii_64k[1][i] = i & 0xFF;
}
}
apple_ii_64k[0][0xC000] = 0x00;
apple_ii_64k[1][0xC000] = 0x00;
}
/* -------------------------------------------------------------------------
void c_initialize_sound()
------------------------------------------------------------------------- */
void c_initialize_sound()
{
int i;
for (i = 0xC030; i < 0xC040; i++)
cpu65_vmem[i].r = cpu65_vmem[i].w =
(sound_mode && soundAllowed) ? read_speaker_toggle_pc : ram_nop;
}
#ifdef APPLE_IIE
/* -------------------------------------------------------------------------
c_initialize_iie_switches
------------------------------------------------------------------------- */
void c_initialize_iie_switches() {
base_stackzp = apple_ii_64k[0];
base_d000_rd = apple_ii_64k[0];
base_d000_wrt = language_banks[0] - 0xD000;
base_e000_rd = apple_ii_64k[0];
base_e000_wrt = language_card[0] - 0xE000;
base_ramrd = apple_ii_64k[0];
base_ramwrt = apple_ii_64k[0];
base_textrd = apple_ii_64k[0];
base_textwrt = apple_ii_64k[0];
base_hgrrd = apple_ii_64k[0];
base_hgrwrt= apple_ii_64k[0];
base_c3rom = apple_ii_64k[1]; /* c3rom internal */
c8rom_offset = 0x10000; /* c8rom internal */
base_cxrom = apple_ii_64k[0]; /* cxrom peripheral */
}
#endif
/* -------------------------------------------------------------------------
void c_initialize_vm()
------------------------------------------------------------------------- */
void c_initialize_vm() {
c_initialize_font(); /* font already read in */
c_initialize_apple_ii_memory(); /* read in rom memory */
c_initialize_tables(); /* read/write memory jump tables */
c_initialize_sound(); /* sound system */
c_init_6(); /* drive ][, slot 6 */
#ifdef APPLE_IIE
c_initialize_iie_switches(); /* set the //e softswitches */
#endif
#ifdef MOUSE_EMULATION
c_initialize_mouse();
#endif
}
/* -------------------------------------------------------------------------
void c_initialize_firsttime()
------------------------------------------------------------------------- */
static void reinitialize(void)
{
int i;
#ifdef DEBUGGER
/* reset the watchpoints and breakpoints */
for (i=0; i<MAX_BRKPTS; i++) {
breakpoints[i] = -1;
watchpoints[i] = -1;
}
for (i=0; i<0x100; i++) {
op_breakpoints[(unsigned char)i] = 0;
}
#endif
c_initialize_vm();
softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;
video_setpage( 0 );
video_redraw();
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE)
cpu65_set(CPU65_C02);
else
#endif
if (apple_mode == IIU_MODE)
cpu65_set(CPU65_NMOS);
else
cpu65_set(CPU65_NMOS|CPU65_FAULT);
}
static void c_initialize_firsttime()
{
/* get IO permission for speaker port. */
if (/*ioperm(0x42, 1, 1) ||*/ ioperm(0x61, 1, 1)) {
perror("ioperm");
printf("cannot get port access to PC speaker.\n");
printf("sound will not be used.\n");
soundAllowed=0;
} else
soundAllowed=1;
/* read in system files and calculate system defaults */
c_load_interface_font();
/* initialize the video system */
video_init();
/* Enable periodic updates */
signal(SIGVTALRM,c_periodic_update);
setitimer(ITIMER_VIRTUAL,&timer_on,0);
reinitialize();
}
void c_read_random() {
random_value = (unsigned char)(rand() >> 8);
}
int main(int sargc, char *sargv[])
{
int i;
argc = sargc;
argv = sargv;
for (i = 1; i < argc; i++)
{
/*
if (strcmp(argv[i], "-vga") == 0)
force_vga_mode = 1;
*/
}
load_settings(); /* user prefs */
c_initialize_firsttime(); /* init svga graphics and vm */
for (;;) {
/* execute the emulator */
cpu65_run();
reinitialize();
}
/* never reached */
}

261
src/misc.h Normal file
View File

@ -0,0 +1,261 @@
/*
* Apple // emulator for Linux: Miscellaneous defines
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef MISC_H
#define MISC_H
#ifndef __ASSEMBLER__
#include <unistd.h>
#include <sys/types.h>
#define SW_TEXT 0xC050
#define SW_MIXED 0xC052
#define SW_PAGE2 0xC054
#define SW_HIRES 0xC056
#ifdef APPLE_IIE
#define SW_80STORE 0xC000
#define SW_RAMRD 0xC002
#define SW_RAMWRT 0xC004
#define SW_ALTZP 0xC008
#define SW_80COL 0xC00C
#define SW_ALTCHAR 0xC00E
#define SW_SLOTC3ROM 0xC00B /* anomaly */
#define SW_SLOTCXROM 0xC006
#define SW_DHIRES 0xC05E
#define SW_IOUDIS 0xC07E
#endif
extern const struct itimerval timer_on,timer_off;
/* Text characters */
extern const unsigned char ucase_glyphs[0x200];
extern const unsigned char lcase_glyphs[0x100];
extern const unsigned char mousetext_glyphs[0x100];
extern const unsigned char interface_glyphs[88];
unsigned char apple_ii_64k[2][65536]; /* 128k memory */
/* language card memory and settings */
unsigned char language_card[2][8192], language_banks[2][8192];
/* misc stuff */
int soundAllowed;
unsigned char random_value;
/* global ref to commandline args */
char **argv;
int argc;
/* misc arrays */
#define TEMPSIZE 4096
unsigned char temp[ TEMPSIZE ];/* should be >=4096 (stuff depends on this) */
#ifdef APPLE_IIE
/* memory offsets from softswitches */
int c8rom_offset;
extern unsigned char *base_ramrd;
extern unsigned char *base_ramwrt;
extern unsigned char *base_textrd;
extern unsigned char *base_textwrt;
extern unsigned char *base_hgrrd;
extern unsigned char *base_hgrwrt;
extern unsigned char *base_stackzp;
extern unsigned char *base_d000_rd;
extern unsigned char *base_e000_rd;
extern unsigned char *base_d000_wrt;
extern unsigned char *base_e000_wrt;
extern unsigned char *base_c3rom;
extern unsigned char *base_cxrom;
#endif /* APPLE_IIE */
/* softswitches */
extern int softswitches;
#endif /* !__ASSEMBLER__ */
#define SS_TEXT 0x00000001
#define SS_MIXED 0x00000002
#define SS_HIRES 0x00000004
#define SS_PAGE2 0x00000008
#define SS_BANK2 0x00000010
#define SS_LCRAM 0x00000020
#define SS_LCSEC 0x00000040 /* check for double read */
#define SS_LCWRT 0x00000080 /* LC write enable */
#define SS_80STORE 0x00000100
#define SS_80COL 0x00000200
#define SS_RAMRD 0x00000400
#define SS_RAMWRT 0x00000800
#define SS_ALTZP 0x00001000
#define SS_DHIRES 0x00002000
#define SS_IOUDIS 0x00004000
#define SS_CXROM 0x00008000
#define SS_C3ROM 0x00010000
#define SS_ALTCHAR 0x00020000
/* Pseudo soft switches. These are actually functions of other SSes, but are
* tiresome to calculate as needed.
*
*/
#define SS_SCREEN 0x00040000 /* PAGE2 && !80STORE */
#define SS_TEXTRD 0x00080000 /* (PAGE2 && 80STORE) ||
(RAMRD && !80STORE) */
#define SS_TEXTWRT 0x00100000 /* (PAGE2 && 80STORE) ||
(RAMWRT && !80STORE) */
#define SS_HGRRD 0x00200000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMRD && !(80STORE && HIRES) */
#define SS_HGRWRT 0x00400000 /* (PAGE2 && 80STORE && HIRES) ||
(RAMWRT && !(80STORE && HIRES)) */
#ifndef __ASSEMBLER__
/* -------------------------------------------------------------------------
misc.c functions
------------------------------------------------------------------------- */
void c_initialize_sound();
void c_initialize_font();
void c_initialize_vm();
void c_read_random();
/* virtual memory compacter */
void pre_compact(void);
void compact(void);
/* vm hooks */
void ram_nop(),
write_ram_default(),
write_unmapped_softswitch(),
read_ram_default(),
read_random(),
read_unmapped_softswitch(),
read_keyboard(),
read_keyboard_strobe(),
read_speaker_toggle_pc(),
read_switch_primary_page(),
read_switch_secondary_page(),
read_switch_graphics(),
read_switch_text(),
read_switch_no_mixed(),
read_switch_mixed(),
read_switch_lores(),
read_switch_hires(),
read_button0(),
read_button1(),
read_button2(),
read_gc0(),
read_gc1(),
read_gc_strobe(),
lc_c080(),
lc_c081(),
lc_c082(),
lc_c083(),
lc_c088(),
lc_c089(),
lc_c08a(),
lc_c08b(),
write_ram_bank(),
read_ram_bank(),
write_ram_lc(),
read_ram_lc();
#ifdef APPLE_IIE
void iie_write_ram_default(),
iie_read_ram_default(),
/* //e text pages */
iie_read_ram_text_page0(),
iie_write_screen_hole_text_page0(),
/* //e hires page 0 */
iie_read_ram_hires_page0(),
iie_write_screen_hole_hires_page0(),
/* //e zpage,stack, ram banks */
iie_read_ram_zpage_and_stack(),
iie_write_ram_zpage_and_stack(),
iie_read_slot3(),
iie_read_slotx(),
iie_read_slot_expansion(),
iie_disable_slot_expansion(),
iie_read_gc2(),
iie_read_gc3(),
iie_c080(),
iie_c081(),
iie_c083(),
iie_c088(),
iie_c089(),
iie_c08b(),
/* //e toggle softswitches */
iie_ramrd_main(),
iie_ramrd_aux(),
iie_ramwrt_main(),
iie_ramwrt_aux(),
iie_80store_off(),
iie_80store_on(),
iie_altzp_main(),
iie_altzp_aux(),
iie_80col_off(),
iie_80col_on(),
iie_altchar_off(),
iie_altchar_on(),
iie_c3rom_peripheral(),
iie_c3rom_internal(),
iie_cxrom_peripheral(),
iie_cxrom_internal(),
iie_ioudis_on(),
iie_ioudis_off(),
iie_dhires_on(),
iie_dhires_off(),
iie_hires_off(),
iie_hires_on(),
iie_page2_on(),
iie_page2_off(),
/* //e check softswitche settings */
iie_check_80store(),
iie_check_bank(),
iie_check_lcram(),
iie_check_ramrd(),
iie_check_ramwrt(),
iie_check_altzp(),
iie_check_c3rom(),
iie_check_cxrom(),
iie_check_80col(),
iie_check_altchar(),
iie_check_text(),
iie_check_mixed(),
iie_check_hires(),
iie_check_page2(),
iie_check_ioudis(),
iie_check_dhires(),
iie_check_vbl();
#endif /* APPLE_IIE */
#endif /* !__ASSEMBLER__ */
#endif

820
src/opcodes.c Normal file
View File

@ -0,0 +1,820 @@
/*
* Apple // emulator for Linux: Opcode tables for debugger
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include "debug.h"
const char * const disasm_templates[15] =
{
"",
"A",
"#$%02X",
"$%02X",
"$%02X,X",
"$%02X,Y",
"$%02X%02X",
"$%02X%02X,X",
"$%02X%02X,Y",
"($%02X)",
"($%02X,X)",
"($%02X),Y",
"($%02X%02X)",
"($%02X%02X),X",
"$%04X (%c%02X)"
};
const struct opcode_struct opcodes_6502[256] =
{
{"BRK", addr_implied},
{"ORA", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ORA", addr_zeropage},
{"ASL", addr_zeropage},
{"???", addr_implied},
{"PHP", addr_implied},
{"ORA", addr_immediate},
{"ASL", addr_accumulator},
{"???", addr_implied},
{"???", addr_implied},
{"ORA", addr_absolute},
{"ASL", addr_absolute},
{"???", addr_implied},
{"BPL", addr_relative},
{"ORA", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ORA", addr_zeropage_x},
{"ASL", addr_zeropage_x},
{"???", addr_implied},
{"CLC", addr_implied},
{"ORA", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ORA", addr_absolute_x},
{"ASL", addr_absolute_x},
{"???", addr_implied},
{"JSR", addr_absolute},
{"AND", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"BIT", addr_zeropage},
{"AND", addr_zeropage},
{"ROL", addr_zeropage},
{"???", addr_implied},
{"PLP", addr_implied},
{"AND", addr_immediate},
{"ROL", addr_accumulator},
{"???", addr_implied},
{"BIT", addr_absolute},
{"AND", addr_absolute},
{"ROL", addr_absolute},
{"???", addr_implied},
{"BMI", addr_relative},
{"AND", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"AND", addr_zeropage_x},
{"ROL", addr_zeropage_x},
{"???", addr_implied},
{"SEC", addr_implied},
{"AND", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"AND", addr_absolute_x},
{"ROL", addr_absolute_x},
{"???", addr_implied},
{"RTI", addr_implied},
{"EOR", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_zeropage},
{"LSR", addr_zeropage},
{"???", addr_implied},
{"PHA", addr_implied},
{"EOR", addr_immediate},
{"LSR", addr_accumulator},
{"???", addr_implied},
{"JMP", addr_absolute},
{"EOR", addr_absolute},
{"LSR", addr_absolute},
{"???", addr_implied},
{"BVC", addr_relative},
{"EOR", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_zeropage_x},
{"LSR", addr_zeropage_x},
{"???", addr_implied},
{"CLI", addr_implied},
{"EOR", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_absolute_x},
{"LSR", addr_absolute_x},
{"???", addr_implied},
{"RTS", addr_implied},
{"ADC", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ADC", addr_zeropage},
{"ROR", addr_zeropage},
{"???", addr_implied},
{"PLA", addr_implied},
{"ADC", addr_immediate},
{"ROR", addr_accumulator},
{"???", addr_implied},
{"JMP", addr_j_indirect},
{"ADC", addr_absolute},
{"ROR", addr_absolute},
{"???", addr_implied},
{"BVS", addr_relative},
{"ADC", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ADC", addr_zeropage_x},
{"ROR", addr_zeropage_x},
{"???", addr_implied},
{"SEI", addr_implied},
{"ADC", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"ADC", addr_absolute_x},
{"ROR", addr_absolute_x},
{"???", addr_implied},
{"???", addr_implied},
{"STA", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"STY", addr_zeropage},
{"STA", addr_zeropage},
{"STX", addr_zeropage},
{"???", addr_implied},
{"DEY", addr_implied},
{"???", addr_implied},
{"TXA", addr_implied},
{"???", addr_implied},
{"STY", addr_absolute},
{"STA", addr_absolute},
{"STX", addr_absolute},
{"???", addr_implied},
{"BCC", addr_relative},
{"STA", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"STY", addr_zeropage_x},
{"STA", addr_zeropage_x},
{"STX", addr_zeropage_y},
{"???", addr_implied},
{"TYA", addr_implied},
{"STA", addr_absolute_y},
{"TXS", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"STA", addr_absolute_x},
{"???", addr_implied},
{"???", addr_implied},
{"LDY", addr_immediate},
{"LDA", addr_indirect_x},
{"LDX", addr_immediate},
{"???", addr_implied},
{"LDY", addr_zeropage},
{"LDA", addr_zeropage},
{"LDX", addr_zeropage},
{"???", addr_implied},
{"TAY", addr_implied},
{"LDA", addr_immediate},
{"TAX", addr_implied},
{"???", addr_implied},
{"LDY", addr_absolute},
{"LDA", addr_absolute},
{"LDX", addr_absolute},
{"???", addr_implied},
{"BCS", addr_relative},
{"LDA", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"LDY", addr_zeropage_x},
{"LDA", addr_zeropage_x},
{"LDX", addr_zeropage_y},
{"???", addr_implied},
{"CLV", addr_implied},
{"LDA", addr_absolute_y},
{"TSX", addr_implied},
{"???", addr_implied},
{"LDY", addr_absolute_x},
{"LDA", addr_absolute_x},
{"LDX", addr_absolute_y},
{"???", addr_implied},
{"CPY", addr_immediate},
{"CMP", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"CPY", addr_zeropage},
{"CMP", addr_zeropage},
{"DEC", addr_zeropage},
{"???", addr_implied},
{"INY", addr_implied},
{"CMP", addr_immediate},
{"DEX", addr_implied},
{"???", addr_implied},
{"CPY", addr_absolute},
{"CMP", addr_absolute},
{"DEC", addr_absolute},
{"???", addr_implied},
{"BNE", addr_relative},
{"CMP", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"CMP", addr_zeropage_x},
{"DEC", addr_zeropage_x},
{"???", addr_implied},
{"CLD", addr_implied},
{"CMP", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"CMP", addr_absolute_x},
{"DEC", addr_absolute_x},
{"???", addr_implied},
{"CPX", addr_immediate},
{"SBC", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"CPX", addr_zeropage},
{"SBC", addr_zeropage},
{"INC", addr_zeropage},
{"???", addr_implied},
{"INX", addr_implied},
{"SBC", addr_immediate},
{"NOP", addr_implied},
{"???", addr_implied},
{"CPX", addr_absolute},
{"SBC", addr_absolute},
{"INC", addr_absolute},
{"???", addr_implied},
{"BEQ", addr_relative},
{"SBC", addr_indirect_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"SBC", addr_zeropage_x},
{"INC", addr_zeropage_x},
{"???", addr_implied},
{"SED", addr_implied},
{"SBC", addr_absolute_y},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"SBC", addr_absolute_x},
{"INC", addr_absolute_x},
{"???", addr_implied},
};
#ifdef APPLE_IIE
const struct opcode_struct opcodes_65c02[256] =
{
{"BRK", addr_implied},
{"ORA", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"TSB", addr_zeropage},
{"ORA", addr_zeropage},
{"ASL", addr_zeropage},
{"???", addr_implied},
{"PHP", addr_implied},
{"ORA", addr_immediate},
{"ASL", addr_accumulator},
{"???", addr_implied},
{"TSB", addr_absolute},
{"ORA", addr_absolute},
{"ASL", addr_absolute},
{"???", addr_implied},
{"BPL", addr_relative},
{"ORA", addr_indirect_y},
{"ORA", addr_indirect},
{"???", addr_implied},
{"TRB", addr_zeropage},
{"ORA", addr_zeropage_x},
{"ASL", addr_zeropage_x},
{"???", addr_implied},
{"CLC", addr_implied},
{"ORA", addr_absolute_y},
{"INC", addr_accumulator},
{"???", addr_implied},
{"TRB", addr_absolute},
{"ORA", addr_absolute_x},
{"ASL", addr_absolute_x},
{"???", addr_implied},
{"JSR", addr_absolute},
{"AND", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"BIT", addr_zeropage},
{"AND", addr_zeropage},
{"ROL", addr_zeropage},
{"???", addr_implied},
{"PLP", addr_implied},
{"AND", addr_immediate},
{"ROL", addr_accumulator},
{"???", addr_implied},
{"BIT", addr_absolute},
{"AND", addr_absolute},
{"ROL", addr_absolute},
{"???", addr_implied},
{"BMI", addr_relative},
{"AND", addr_indirect_y},
{"AND", addr_indirect},
{"???", addr_implied},
{"BIT", addr_zeropage_x},
{"AND", addr_zeropage_x},
{"ROL", addr_zeropage_x},
{"???", addr_implied},
{"SEC", addr_implied},
{"AND", addr_absolute_y},
{"DEC", addr_accumulator},
{"???", addr_implied},
{"BIT", addr_absolute_x},
{"AND", addr_absolute_x},
{"ROL", addr_absolute_x},
{"???", addr_implied},
{"RTI", addr_implied},
{"EOR", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_zeropage},
{"LSR", addr_zeropage},
{"???", addr_implied},
{"PHA", addr_implied},
{"EOR", addr_immediate},
{"LSR", addr_accumulator},
{"???", addr_implied},
{"JMP", addr_absolute},
{"EOR", addr_absolute},
{"LSR", addr_absolute},
{"???", addr_implied},
{"BVC", addr_relative},
{"EOR", addr_indirect_y},
{"EOR", addr_indirect},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_zeropage_x},
{"LSR", addr_zeropage_x},
{"???", addr_implied},
{"CLI", addr_implied},
{"EOR", addr_absolute_y},
{"PHY", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"EOR", addr_absolute_x},
{"LSR", addr_absolute_x},
{"???", addr_implied},
{"RTS", addr_implied},
{"ADC", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"STZ", addr_zeropage},
{"ADC", addr_zeropage},
{"ROR", addr_zeropage},
{"???", addr_implied},
{"PLA", addr_implied},
{"ADC", addr_immediate},
{"ROR", addr_accumulator},
{"???", addr_implied},
{"JMP", addr_j_indirect},
{"ADC", addr_absolute},
{"ROR", addr_absolute},
{"???", addr_implied},
{"BVS", addr_relative},
{"ADC", addr_indirect_y},
{"ADC", addr_indirect},
{"???", addr_implied},
{"STZ", addr_zeropage_x},
{"ADC", addr_zeropage_x},
{"ROR", addr_zeropage_x},
{"???", addr_implied},
{"SEI", addr_implied},
{"ADC", addr_absolute_y},
{"PLY", addr_implied},
{"???", addr_implied},
{"JMP", addr_j_indirect_x},
{"ADC", addr_absolute_x},
{"ROR", addr_absolute_x},
{"???", addr_implied},
{"BRA", addr_relative},
{"STA", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"STY", addr_zeropage},
{"STA", addr_zeropage},
{"STX", addr_zeropage},
{"???", addr_implied},
{"DEY", addr_implied},
{"BIT", addr_immediate},
{"TXA", addr_implied},
{"???", addr_implied},
{"STY", addr_absolute},
{"STA", addr_absolute},
{"STX", addr_absolute},
{"???", addr_implied},
{"BCC", addr_relative},
{"STA", addr_indirect_y},
{"STA", addr_indirect},
{"???", addr_implied},
{"STY", addr_zeropage_x},
{"STA", addr_zeropage_x},
{"STX", addr_zeropage_y},
{"???", addr_implied},
{"TYA", addr_implied},
{"STA", addr_absolute_y},
{"TXS", addr_implied},
{"???", addr_implied},
{"STZ", addr_absolute},
{"STA", addr_absolute_x},
{"STZ", addr_absolute_x},
{"???", addr_implied},
{"LDY", addr_immediate},
{"LDA", addr_indirect_x},
{"LDX", addr_immediate},
{"???", addr_implied},
{"LDY", addr_zeropage},
{"LDA", addr_zeropage},
{"LDX", addr_zeropage},
{"???", addr_implied},
{"TAY", addr_implied},
{"LDA", addr_immediate},
{"TAX", addr_implied},
{"???", addr_implied},
{"LDY", addr_absolute},
{"LDA", addr_absolute},
{"LDX", addr_absolute},
{"???", addr_implied},
{"BCS", addr_relative},
{"LDA", addr_indirect_y},
{"LDA", addr_indirect},
{"???", addr_implied},
{"LDY", addr_zeropage_x},
{"LDA", addr_zeropage_x},
{"LDX", addr_zeropage_y},
{"???", addr_implied},
{"CLV", addr_implied},
{"LDA", addr_absolute_y},
{"TSX", addr_implied},
{"???", addr_implied},
{"LDY", addr_absolute_x},
{"LDA", addr_absolute_x},
{"LDX", addr_absolute_y},
{"???", addr_implied},
{"CPY", addr_immediate},
{"CMP", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"CPY", addr_zeropage},
{"CMP", addr_zeropage},
{"DEC", addr_zeropage},
{"???", addr_implied},
{"INY", addr_implied},
{"CMP", addr_immediate},
{"DEX", addr_implied},
{"???", addr_implied},
{"CPY", addr_absolute},
{"CMP", addr_absolute},
{"DEC", addr_absolute},
{"???", addr_implied},
{"BNE", addr_relative},
{"CMP", addr_indirect_y},
{"CMP", addr_indirect},
{"???", addr_implied},
{"???", addr_implied},
{"CMP", addr_zeropage_x},
{"DEC", addr_zeropage_x},
{"???", addr_implied},
{"CLD", addr_implied},
{"CMP", addr_absolute_y},
{"PHX", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"CMP", addr_absolute_x},
{"DEC", addr_absolute_x},
{"???", addr_implied},
{"CPX", addr_immediate},
{"SBC", addr_indirect_x},
{"???", addr_implied},
{"???", addr_implied},
{"CPX", addr_zeropage},
{"SBC", addr_zeropage},
{"INC", addr_zeropage},
{"???", addr_implied},
{"INX", addr_implied},
{"SBC", addr_immediate},
{"NOP", addr_implied},
{"???", addr_implied},
{"CPX", addr_absolute},
{"SBC", addr_absolute},
{"INC", addr_absolute},
{"???", addr_implied},
{"BEQ", addr_relative},
{"SBC", addr_indirect_y},
{"SBC", addr_indirect},
{"???", addr_implied},
{"???", addr_implied},
{"SBC", addr_zeropage_x},
{"INC", addr_zeropage_x},
{"???", addr_implied},
{"SED", addr_implied},
{"SBC", addr_absolute_y},
{"PLX", addr_implied},
{"???", addr_implied},
{"???", addr_implied},
{"SBC", addr_absolute_x},
{"INC", addr_absolute_x},
{"???", addr_implied},
};
#endif /* APPLE_IIE */
const struct opcode_struct opcodes_undoc[256] =
{
{"BRK", addr_implied},
{"ORA", addr_indirect_x},
{"hang", addr_implied},
{"lor", addr_indirect_x},
{"nop", addr_zeropage},
{"ORA", addr_zeropage},
{"ASL", addr_zeropage},
{"lor", addr_zeropage},
{"PHP", addr_implied},
{"ORA", addr_immediate},
{"ASL", addr_accumulator},
{"ana", addr_immediate},
{"nop", addr_absolute},
{"ORA", addr_absolute},
{"ASL", addr_absolute},
{"lor", addr_absolute},
{"BPL", addr_relative},
{"ORA", addr_indirect_y},
{"hang", addr_implied},
{"lor", addr_indirect_y},
{"nop", addr_zeropage_x},
{"ORA", addr_zeropage_x},
{"ASL", addr_zeropage_x},
{"lor", addr_zeropage_x},
{"CLC", addr_implied},
{"ORA", addr_absolute_y},
{"nop", addr_implied},
{"lor", addr_absolute_y},
{"nop", addr_absolute_x},
{"ORA", addr_absolute_x},
{"ASL", addr_absolute_x},
{"lor", addr_absolute},
{"JSR", addr_absolute},
{"AND", addr_indirect_x},
{"hang", addr_implied},
{"lan", addr_indirect_x},
{"BIT", addr_zeropage},
{"AND", addr_zeropage},
{"ROL", addr_zeropage},
{"lan", addr_zeropage},
{"PLP", addr_implied},
{"AND", addr_immediate},
{"ROL", addr_accumulator},
{"anb", addr_immediate},
{"BIT", addr_absolute},
{"AND", addr_absolute},
{"ROL", addr_absolute},
{"lan", addr_absolute},
{"BMI", addr_relative},
{"AND", addr_indirect_y},
{"hang", addr_implied},
{"lan", addr_indirect_y},
{"nop", addr_zeropage_x},
{"AND", addr_zeropage_x},
{"ROL", addr_zeropage_x},
{"lan", addr_zeropage_x},
{"SEC", addr_implied},
{"AND", addr_absolute_y},
{"nop", addr_implied},
{"lan", addr_absolute_y},
{"nop", addr_absolute_x},
{"AND", addr_absolute_x},
{"ROL", addr_absolute_x},
{"lan", addr_absolute_x},
{"RTI", addr_implied},
{"EOR", addr_indirect_x},
{"hang", addr_implied},
{"reo", addr_indirect_x},
{"nop", addr_zeropage},
{"EOR", addr_zeropage},
{"LSR", addr_zeropage},
{"reo", addr_zeropage},
{"PHA", addr_implied},
{"EOR", addr_immediate},
{"LSR", addr_accumulator},
{"ram", addr_immediate},
{"JMP", addr_absolute},
{"EOR", addr_absolute},
{"LSR", addr_absolute},
{"reo", addr_absolute},
{"BVC", addr_relative},
{"EOR", addr_indirect_y},
{"hang", addr_implied},
{"reo", addr_indirect_y},
{"nop", addr_zeropage_x},
{"EOR", addr_zeropage_x},
{"LSR", addr_zeropage_x},
{"reo", addr_zeropage_x},
{"CLI", addr_implied},
{"EOR", addr_absolute_y},
{"nop", addr_implied},
{"reo", addr_absolute_y},
{"nop", addr_absolute_x},
{"EOR", addr_absolute_x},
{"LSR", addr_absolute_x},
{"reo", addr_absolute_x},
{"RTS", addr_implied},
{"ADC", addr_indirect_x},
{"hang", addr_implied},
{"rad", addr_indirect_x},
{"nop", addr_zeropage},
{"ADC", addr_zeropage},
{"ROR", addr_zeropage},
{"rad", addr_zeropage},
{"PLA", addr_implied},
{"ADC", addr_immediate},
{"ROR", addr_accumulator},
{"rbm", addr_immediate},
{"JMP", addr_j_indirect},
{"ADC", addr_absolute},
{"ROR", addr_absolute},
{"rad", addr_absolute},
{"BVS", addr_relative},
{"ADC", addr_indirect_y},
{"hang", addr_implied},
{"rad", addr_indirect_y},
{"nop", addr_zeropage_x},
{"ADC", addr_zeropage_x},
{"ROR", addr_zeropage_x},
{"rad", addr_zeropage_x},
{"SEI", addr_implied},
{"ADC", addr_absolute_y},
{"nop", addr_implied},
{"rad", addr_absolute_y},
{"nop", addr_absolute_x},
{"ADC", addr_absolute_x},
{"ROR", addr_absolute_x},
{"rad", addr_absolute_x},
{"nop", addr_immediate},
{"STA", addr_indirect_x},
{"nop", addr_immediate},
{"aax", addr_indirect_x},
{"STY", addr_zeropage},
{"STA", addr_zeropage},
{"STX", addr_zeropage},
{"aax", addr_zeropage},
{"DEY", addr_implied},
{"nop", addr_immediate},
{"TXA", addr_implied},
{"xma", addr_immediate},
{"STY", addr_absolute},
{"STA", addr_absolute},
{"STX", addr_absolute},
{"aax", addr_absolute},
{"BCC", addr_relative},
{"STA", addr_indirect_y},
{"hang", addr_implied},
{"aax", addr_indirect_y},
{"STY", addr_zeropage_x},
{"STA", addr_zeropage_x},
{"STX", addr_zeropage_y},
{"aax", addr_zeropage_y},
{"TYA", addr_implied},
{"STA", addr_absolute_y},
{"TXS", addr_implied},
{"axs", addr_absolute_y},
{"tey", addr_absolute_x},
{"STA", addr_absolute_x},
{"tex", addr_absolute_y},
{"tea", addr_absolute_y},
{"LDY", addr_immediate},
{"LDA", addr_indirect_x},
{"LDX", addr_immediate},
{"lax", addr_indirect_x},
{"LDY", addr_zeropage},
{"LDA", addr_zeropage},
{"LDX", addr_zeropage},
{"lax", addr_zeropage},
{"TAY", addr_implied},
{"LDA", addr_immediate},
{"TAX", addr_implied},
{"ama", addr_immediate},
{"LDY", addr_absolute},
{"LDA", addr_absolute},
{"LDX", addr_absolute},
{"lax", addr_absolute},
{"BCS", addr_relative},
{"LDA", addr_indirect_y},
{"hang", addr_implied},
{"lax", addr_indirect_y},
{"LDY", addr_zeropage_x},
{"LDA", addr_zeropage_x},
{"LDX", addr_zeropage_y},
{"laz", addr_zeropage_y},
{"CLV", addr_implied},
{"LDA", addr_absolute_y},
{"TSX", addr_implied},
{"las", addr_absolute_y},
{"LDY", addr_absolute_x},
{"LDA", addr_absolute_x},
{"LDX", addr_absolute_y},
{"lax", addr_absolute_y},
{"CPY", addr_immediate},
{"CMP", addr_indirect_x},
{"nop", addr_immediate},
{"dcp", addr_indirect_x},
{"CPY", addr_zeropage},
{"CMP", addr_zeropage},
{"DEC", addr_zeropage},
{"dcp", addr_zeropage},
{"INY", addr_implied},
{"CMP", addr_immediate},
{"DEX", addr_implied},
{"axm", addr_immediate},
{"CPY", addr_absolute},
{"CMP", addr_absolute},
{"DEC", addr_absolute},
{"dcp", addr_absolute},
{"BNE", addr_relative},
{"CMP", addr_indirect_y},
{"hang", addr_implied},
{"dcp", addr_indirect_y},
{"nop", addr_zeropage_x},
{"CMP", addr_zeropage_x},
{"DEC", addr_zeropage_x},
{"dcp", addr_zeropage_x},
{"CLD", addr_implied},
{"CMP", addr_absolute_y},
{"nop", addr_implied},
{"dcp", addr_absolute_y},
{"nop", addr_absolute_x},
{"CMP", addr_absolute_x},
{"DEC", addr_absolute_x},
{"dcp", addr_absolute_x},
{"CPX", addr_immediate},
{"SBC", addr_indirect_x},
{"nop", addr_immediate},
{"isb", addr_indirect_x},
{"CPX", addr_zeropage},
{"SBC", addr_zeropage},
{"INC", addr_zeropage},
{"isb", addr_zeropage},
{"INX", addr_implied},
{"SBC", addr_immediate},
{"NOP", addr_implied},
{"zbc", addr_immediate},
{"CPX", addr_absolute},
{"SBC", addr_absolute},
{"INC", addr_absolute},
{"isb", addr_absolute},
{"BEQ", addr_relative},
{"SBC", addr_indirect_y},
{"hang", addr_implied},
{"isb", addr_indirect_y},
{"nop", addr_zeropage_x},
{"SBC", addr_zeropage_x},
{"INC", addr_zeropage_x},
{"isb", addr_zeropage_x},
{"SED", addr_implied},
{"SBC", addr_absolute_y},
{"nop", addr_implied},
{"isb", addr_absolute_y},
{"nop", addr_absolute_x},
{"SBC", addr_absolute_x},
{"INC", addr_absolute_x},
{"isb", addr_absolute_x},
};

412
src/prefs.c Normal file
View File

@ -0,0 +1,412 @@
/*
* Apple // emulator for Linux: Preferences file maintenance
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "misc.h"
#include "prefs.h"
#include "keys.h"
#include "interface.h"
#include "cpu.h"
#define PRM_NONE 0
#define PRM_SPEED 1
#define PRM_MODE 2
#define PRM_DISK_PATH 3
#define PRM_HIRES_COLOR 4
#define PRM_SOUND 5
#define PRM_JOY_INPUT 6
#define PRM_JOY_RANGE 7
#define PRM_JOY_OX 8
#define PRM_JOY_OY 9
#define PRM_JOY_PC_CALIBRATE 10
#define PRM_JOY_KYBD_SENSITIVITY 11
#define PRM_ROM_PATH 12
char system_path[SYSSIZE];
char disk_path[DISKSIZE];
int apple_mode;
int sound_mode;
int color_mode;
short joy_mode;
short joy_step;
short joy_center_x;
short joy_center_y;
short joy_range;
short half_joy_range;
#ifdef PC_JOYSTICK
int js_center_x;
int js_center_y;
long js_timelimit;
int js_max_x;
int js_max_y;
int js_min_x;
int js_min_y;
#endif /* PC_JOYSTICK */
static char *config_filename;
struct match_table
{
const char *tag;
int value;
};
static const struct match_table prefs_table[] =
{
{"speed", PRM_SPEED},
{"mode", PRM_MODE},
{"path", PRM_DISK_PATH},
{"disk path", PRM_DISK_PATH},
{"disk_path", PRM_DISK_PATH},
{"path", PRM_DISK_PATH},
{"color", PRM_HIRES_COLOR},
{"sound", PRM_SOUND},
{"joystick", PRM_JOY_INPUT},
{"joy range", PRM_JOY_RANGE},
{"joystick range", PRM_JOY_RANGE},
{"joy_range", PRM_JOY_RANGE},
{"origin_x", PRM_JOY_OX},
{"origin_y", PRM_JOY_OY},
{"pc joystick parms", PRM_JOY_PC_CALIBRATE},
{"pc_joystick_parms", PRM_JOY_PC_CALIBRATE},
{"sensitivity", PRM_JOY_KYBD_SENSITIVITY},
{"system path", PRM_ROM_PATH},
{"system_path", PRM_ROM_PATH},
{0, PRM_NONE}
};
static const struct match_table modes_table[] =
{
{"][+", II_MODE},
{"][+ undocumented", IIU_MODE},
#ifdef APPLE_IIE
{"//e", IIE_MODE},
{0, IIE_MODE}
#else /* !APPLE_IIE */
{0, IIU_MODE}
#endif /* !APPLE_IIE */
};
static const struct match_table color_table[] =
{
{"black/white", NO_COLOR},
{"lazy color", LAZY_COLOR},
{"color", COLOR},
{"lazy interpolated", LAZY_INTERP},
{"interpolated", INTERP},
{"off", 0},
{"on", COLOR},
{0, COLOR}
};
static const struct match_table sound_table[] =
{
{"off", 0},
{"pc_speaker", 1},
{"on", 1},
{0, 1},
};
static const struct match_table joy_input_table[] =
{
{"off", JOY_OFF},
{"keyboard", JOY_KYBD},
{"linear", JOY_KYBD},
#ifdef PC_JOYSTICK
{"pc joystick", JOY_PCJOY},
{"pc_joystick", JOY_PCJOY},
#endif /* PC_JOYSTICK */
#if 0
{"digital", JOY_DIGITAL},
#endif /* 0 */
{0, JOY_KYBD}
};
/* Find the number assigned to KEYWORD in a match table PARADIGM. If no match,
* then the value associated with the terminating entry is used as a
* default. */
static int
match (const struct match_table *paradigm, const char *keyword)
{
while (paradigm->tag && strcasecmp (paradigm->tag, keyword))
paradigm++;
return paradigm->value;
}
/* Reverse match -- find a keyword associated with number KEY in
* PARADIGM. The first match is used -- synonym keywords appearing later
* in the table are not chosen.
*
* A null is returned for no match.
*/
static const char *reverse_match (const struct match_table *paradigm, int key)
{
while (paradigm->tag && key != paradigm->value)
paradigm++;
return paradigm->tag;
}
/* Eat leading and trailing whitespace of string X. The old string is
* overwritten and a new pointer is returned.
*/
static char *
clean_string (char *x)
{
size_t y;
/* Leading white space */
while (isspace (*x)) x++;
/* Trailing white space */
y = strlen (x);
while (y && x[y--] == ' ');
x[y] = 0;
return x;
}
/* Load the configuration. Must be called *once* at start. */
void
load_settings (void)
{
/* set system defaults before user defaults. */
strcpy (disk_path, "./disks");
strcpy (system_path, "./rom");
{
const char *homedir;
homedir = getenv ("HOME");
config_filename = malloc (strlen (homedir) + 9);
strcpy (config_filename, homedir);
strcat (config_filename, "/.apple2");
/* config_filename is left allocated for convinence in
* save_settings */
}
{
FILE *config_file;
char *buffer = 0;
size_t size = 0;
config_file = fopen (config_filename, "r");
if (config_file == NULL)
{
printf (
"Warning. Cannot open the .apple2 system defaults file.\n"
"Make sure it's readable in your home directory.");
printf ("Press RETURN to continue...");
getchar ();
return;
}
while (getline (&buffer, &size, config_file) != -1)
{
char *parameter;
char *argument;
/* Split line between parameter and argument */
parameter = buffer;
argument = strchr (buffer, '=');
argument[0] = 0;
argument++;
parameter = clean_string (parameter);
argument = clean_string (argument);
switch (match (prefs_table, parameter))
{
case PRM_NONE:
fprintf (stderr, "Unrecognized config parameter `%s'", parameter);
break;
case PRM_SPEED:
{
int x;
x = strtol (argument, 0, 0);
if (x < 0)
x = 0;
cpu65_delay = MAX_APPLE_DELAY - x + 1;
if (cpu65_delay < 1)
cpu65_delay = 1;
}
break;
case PRM_MODE:
apple_mode = match (modes_table, argument);
break;
case PRM_DISK_PATH:
strncpy (disk_path, argument, DISKSIZE);
break;
case PRM_HIRES_COLOR:
color_mode = match (color_table, argument);
break;
case PRM_SOUND:
sound_mode = match (sound_table, argument);
break;
case PRM_JOY_INPUT:
joy_mode = match (joy_input_table, argument);
break;
case PRM_JOY_RANGE:
joy_range = strtol (argument, 0, 0);
if (joy_range < 10)
joy_range = 10;
else if (joy_range > 256)
joy_range = 256;
half_joy_range = joy_range / 2;
if (joy_center_x > joy_range)
joy_center_x = half_joy_range;
if (joy_center_y > joy_range)
joy_center_y = half_joy_range;
break;
case PRM_JOY_OX:
joy_center_x = strtol (argument, 0, 0);
if (joy_center_x < 0)
joy_center_x = 0;
else if (joy_center_x > 255)
joy_center_x = 255;
if (joy_center_x > joy_range)
joy_center_x = half_joy_range;
break;
case PRM_JOY_OY:
joy_center_y = strtol (argument, 0, 0);
if (joy_center_y < 0)
joy_center_y = 0;
else if (joy_center_y > 255)
joy_center_y = 255;
if (joy_center_y > joy_range)
joy_center_y = half_joy_range;
break;
case PRM_JOY_PC_CALIBRATE:
#ifdef PC_JOYSTICK
/* pc joystick parms generated by the calibration routine
(shouldn't need to hand tweak these) = origin_x origin_y max_x
min_x max_y min_y js_timelimit */
js_center_x = strtol (argument, &argument, 10);
js_center_y = strtol (argument, &argument, 10);
js_max_x = strtol (argument, &argument, 10);
if (js_max_x < 0)
js_max_x = 0;
js_min_x = strtol (argument, &argument, 10);
if (js_min_x < 0)
js_min_x = 0;
js_max_y = strtol (argument, &argument, 10);
if (js_max_y < 0)
js_max_y = 0;
js_min_y = strtol (argument, &argument, 10);
if (js_min_y < 0)
js_min_y = 0;
js_timelimit = strtol (argument, &argument, 10);
if (js_timelimit < 2)
js_timelimit = 2;
c_open_joystick ();
c_calculate_joystick_parms (); /* calculate the associated parms */
#endif
case PRM_JOY_KYBD_SENSITIVITY:
joy_step = strtol (argument, 0, 0);
if (joy_step < 1)
joy_step = 1;
else if (joy_step > 100)
joy_step = 100;
break;
case PRM_ROM_PATH:
strncpy (system_path, argument, SYSSIZE);
break;
}
}
fclose (config_file);
}
}
/* Save the configuration */
void
save_settings (void)
{
FILE *config_file;
config_file = fopen (config_filename, "w");
if (config_file == NULL)
{
printf (
"Cannot open the .apple2 system defaults file for writing.\n"
"Make sure it has rw permission in your home directory.");
return;
}
fprintf (config_file,
"speed = %d\n"
"mode = %s\n"
"disk path = %s\n"
"color = %s\n"
"sound = %s\n"
"joystick = %s\n"
"joystick range = %d\n"
"origin_x = %d\n"
"origin_y = %d\n"
"sensitivity = %d%%\n"
"system path = %s\n",
MAX_APPLE_DELAY + 1 - cpu65_delay,
reverse_match (modes_table, apple_mode),
disk_path,
reverse_match (color_table, color_mode),
reverse_match (sound_table, sound_mode),
reverse_match (joy_input_table, joy_mode),
joy_range,
joy_center_x,
joy_center_y,
joy_step,
system_path);
#ifdef PC_JOYSTICK
fprintf (config_file,
"pc joystick parms = %d %d %d %d %d %d %ld\n",
js_center_x, js_center_y, js_max_x, js_min_x,
js_max_y, js_min_y, js_timelimit);
#endif
fclose (config_file);
}

74
src/prefs.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Apple // emulator for Linux: Configuration defines
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef PREFS_H
#define PREFS_H
#ifndef __ASSEMBLER__
#define SYSSIZE 4096
extern char system_path[SYSSIZE];
#define DISKSIZE 4096
extern char disk_path[DISKSIZE];
extern int apple_mode; /* undocumented instructions or //e mode */
extern int sound_mode; /* PC speaker or OFF */
extern int color_mode;
/* generic joystick settings */
extern short joy_mode;
extern short joy_step;
extern short joy_center_x;
extern short joy_center_y;
extern short joy_range;
extern short half_joy_range;
#ifdef PC_JOYSTICK
/* real joystick settings */
extern int js_center_x;
extern int js_center_y;
extern long js_timelimit;
extern int js_max_x;
extern int js_max_y;
extern int js_min_x;
extern int js_min_y;
#endif /* PC_JOYSTICK */
/* functions in prefs.c */
extern void load_settings(void);
extern void save_settings(void);
#endif /* !__ASSEMBLER__ */
/* values for apple_mode */
#define IIE_MODE 2
#define IIU_MODE 1
#define II_MODE 0
/* values for color_mode */
#define NO_COLOR 0
#define LAZY_COLOR 1
#define COLOR 2
#define LAZY_INTERP 3
#define INTERP 4
/* values for joy_mode */
#define JOY_OFF 0
#define JOY_KYBD 1
#define JOY_DIGITAL 2
#define JOY_PCJOY 3
#endif /* PREFS_H */

215
src/svideo.c Normal file
View File

@ -0,0 +1,215 @@
/*
* Apple // emulator for Linux: svgalib graphics support
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <vga.h>
#include <vgakeyboard.h>
#include <string.h>
#include <stdio.h>
#include <sys/kd.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "video.h"
#include "misc.h"
#include "keys.h"
/* I need at least 560x192 for 80col. it seems that direct linear
* framebuffer access to anything in the realm of 640x480x256 not
* standard with vga/svga?
* Memory sizes are hardcode here. ugly ugly ugly.
*/
static unsigned char *svga_GM; /* SVGA base address of graphic area */
static unsigned char vga_mem_page_0[64000]; /* page0 framebuffer */
static unsigned char vga_mem_page_1[64000]; /* page1 framebuffer */
/* -------------------------------------------------------------------------
video_setpage(p): Switch to screen page p
------------------------------------------------------------------------- */
void video_setpage(int p)
{
if (p == video__current_page) return;
if (p)
{
memcpy(vga_mem_page_0,svga_GM,64000);
memcpy(svga_GM,vga_mem_page_1,64000);
video__current_page = 1;
video__fb1 = vga_mem_page_0;
video__fb2 = svga_GM;
}
else
{
memcpy(vga_mem_page_1,svga_GM,64000);
memcpy(svga_GM,vga_mem_page_0,64000);
video__current_page = 0;
video__fb1 = svga_GM;
video__fb2 = vga_mem_page_1;
}
}
/* -------------------------------------------------------------------------
c_initialize_colors(): Initialize color palette
------------------------------------------------------------------------- */
static void c_initialize_colors()
{
static unsigned int col2[ 3 ] = { 27, 40, 62 };
int i, j;
/* align the palette for hires graphics */
for (i = 0; i < 8; i++)
for (j = 0; j < 3; j++)
vga_setpalette( j+i*3+32, (i & 1) ? col2[ j ] : 0,
(i & 2) ? col2[ j ] : 0,
(i & 4) ? col2[ j ] : 0 );
vga_setpalette( COLOR_FLASHING_BLACK, 0, 0, 0 );
vga_setpalette( COLOR_FLASHING_WHITE, 63, 63, 63 );
/* dhires colors are bass-ackwards because it's easier for me to
deal with the endianness. */
vga_setpalette( 0x0, 0, 0, 0 ); /* (0) Black */
vga_setpalette( 0x1, 0, 0, 32 ); /* (2) Dark Blue */
vga_setpalette( 0x2, 0, 36, 0 ); /* (4) Dark Green */
vga_setpalette( 0x3, 28, 6, 63 ); /* (6) Medium Blue */
vga_setpalette( 0x4, 37, 21, 10 ); /* (8) Brown */
vga_setpalette( 0x5, 37, 42, 42 ); /* (a) Light Grey */
vga_setpalette( 0x6, 0, 63, 0 ); /* (c) Green */
vga_setpalette( 0x7, 32, 63, 32 ); /* (e) Aqua */
vga_setpalette( 0x8, 48, 0, 12 ); /* (1) Magenta */
vga_setpalette( 0x9, 41, 13, 42 ); /* (3) Purple */
vga_setpalette( 0xa, 26, 26, 26 ); /* (5) Light Grey */
vga_setpalette( 0xb, 3, 47, 58 ); /* (7) Light Blue */
vga_setpalette( 0xc, 63, 6, 11 ); /* (9) Orange */
vga_setpalette( 0xd, 63, 39, 37 ); /* (b) Pink */
vga_setpalette( 0xe, 63, 63, 0 ); /* (d) Yellow */
vga_setpalette( 0xf, 63, 63, 63 ); /* (f) White */
/* lores colors (<<4) */
vga_setpalette(0x10, 48, 0, 12 ); /* Magenta */
vga_setpalette(0x20, 0, 0, 32 ); /* Dark Blue */
vga_setpalette(0x30, 41, 13, 42 ); /* Purple */
vga_setpalette(0x40, 0, 36, 0 ); /* Dark Green */
vga_setpalette(0x50, 26, 26, 26 ); /* Dark Gray */
vga_setpalette(0x60, 28, 6, 63 ); /* Medium Blue */
vga_setpalette(0x70, 3, 47, 58 ); /* Light Blue */
vga_setpalette(0x80, 37, 21, 10 ); /* Brown */
vga_setpalette(0x90, 63, 6, 11 ); /* Orange */
vga_setpalette(0xa0, 37, 42, 42 ); /* Light Grey */
vga_setpalette(0xb0, 63, 39, 37 ); /* Pink */
vga_setpalette(0xc0, 0, 63, 0 ); /* Green */
vga_setpalette(0xd0, 63, 63, 0 ); /* Yellow */
vga_setpalette(0xe0, 32, 63, 32 ); /* Aqua */
vga_setpalette(0xf0, 63, 63, 63 ); /* White */
}
/* -------------------------------------------------------------------------
c_initialize_keyboard()
------------------------------------------------------------------------- */
static void c_initialize_keyboard()
{
if (keyboard_init()) {
printf("Error: Could not switch to RAW keyboard mode.\n");
exit(-1);
}
keyboard_translatekeys(DONT_CATCH_CTRLC);
keyboard_seteventhandler( c_read_raw_key );
}
static void c_flash_cursor(int on) {
if (!on) {
vga_setpalette( COLOR_FLASHING_BLACK, 0, 0, 0 );
vga_setpalette( COLOR_FLASHING_WHITE, 63, 63, 63 );
} else {
vga_setpalette( COLOR_FLASHING_BLACK, 63, 63, 63 );
vga_setpalette( COLOR_FLASHING_WHITE, 0, 0, 0 );
}
}
/* -------------------------------------------------------------------------
video_init()
------------------------------------------------------------------------- */
void video_init(void) {
/* I'm forcing VGA mode since it seems to be supported by
* the lowest common denominator cards.
*/
printf("Using standard VGA 320x200 mode.\n");
printf("Press RETURN to continue...");
getchar();
vga_setchipset( VGA );
if (vga_init()) {
printf("Cannot initialize svgalib!\n");
exit(1);
}
vga_setmode( G320x200x256 );
/* vga_claimvideomemory( 131072 );*/
c_initialize_keyboard();
svga_GM = video__fb1 = vga_getgraphmem();
video__fb2 = vga_mem_page_1;
memset(video__fb1,0,64000); /* start as black */
memset(video__fb2,0,64000);
c_initialize_colors();
}
void video_shutdown(void) {
vga_setmode(TEXT);
keyboard_close();
}
void video_sync(int block)
{
static int flash_count;
if (block)
{
/* keyboard_waitforupdate(); --- seems to cause bad crashes... */
usleep(TIMER_DELAY);
keyboard_update();
}
else
keyboard_update();
switch (++flash_count)
{
case 6:
c_flash_cursor(1);
break;
case 12:
c_flash_cursor(0);
flash_count = 0;
break;
default:
break;
}
}

232
src/video.h Normal file
View File

@ -0,0 +1,232 @@
/*
* Apple // emulator for Linux: Video definitions
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#ifndef A2_VIDEO_H
#define A2_VIDEO_H
#ifndef __ASSEMBLER__
/* Prepare the video system, converting console to graphics mode, or
* opening X window, or whatever. This is called only once when the
* emulator is run
*/
void video_init(void);
/* Undo anything done by video_init. This is called before exiting the
* emulator.
*/
void video_shutdown(void);
/* Setup the display. This may be called multiple times in a run, and is
* used when graphics parameters (II+ vs //e, hires color representation) may
* have changed.
*
* In future, all relevant information will be communicated through
* FLAGS. For now, however, it is ignored and global variables are used
* instead.
*
* This function is responsible for inserting any needed video-specific hooks
* into the 6502 memory indirection table. It should *not* hook the
* soft-switches.
*
*/
void video_set(int flags);
/* Set the font used by the display. QTY characters are loaded starting
* with FIRST, from DATA. DATA contains 8 bytes for each character, each
* byte representing a row (top-to-bottom). The row byte contains 7
* pixels in little-endian format.
*
* MODE selects the colors to use
*
* 0 - Normal text
* 1 - MouseText (usually treat as Normal)
* 2 - Inverse
* 3 - Flash
*
* The extra MouseText mode is in case we want to emulate certain RGB
* adaptors which color normal text and MouseText differently. I had one
* once for a //c.
*/
void video_loadfont(int first,
int qty,
const unsigned char *data,
int mode);
/* Redraw the display. This is called after exiting an interface display,
* when changes have been made to the Apple's emulated framebuffer that
* bypass the driver's hooks, or when the video mode has changed.
*/
void video_redraw(void);
/* Change the displayed video page to PAGE
* 0 - Page 1: $400-$7ff/$2000-$3fff
* 1 - Page 2: $800-$bff/$4000-$5fff
*/
void video_setpage(int page);
/* Like loadfont, but writes to a seperate 256 character table used by
* video_plotchar and not the apple text-mode display.
*/
void video_loadfont_int(int first, int qty, const unsigned char *data);
/* Plot a character to the text mode screen, *not* writing to apple
* memory. This is used by the interface screens.
*
* ROW, COL, and CODE are self-expanatory. COLOR gives the color scheme
* to use:
*
* 0 - Green text on Black background
* 1 - Green text on Blue background
* 2 - Red text on Black background
*/
void video_plotchar(int row, int col, int color, unsigned char code);
/* Called at about 30Hz (this may change in future), and when waiting in
* the interface screens.
*
* Should flush any video data to the real screen (if any kind of caching
* is in use), check for keyboard input (presently reported via
* c_read_raw_key), and handle flashing text characters.
*/
void video_sync(int block);
#endif /* !__ASSEMBLER__ */
/**** Private stuff follows *****/
#ifdef _640x400
/* 640x400 mode really isn't what it advertises. It's really 560x384 with 4
* extra bytes on each side for color interpolation hack. This is yet another
* area where I've traded the optimization gain (especially on older slower
* machines) for a standard resolution.
*/
#define SCANWIDTH 568
#define SCANHEIGHT 384
#define SCANSTEP SCANWIDTH-12
#else /* !_640x400 */
#define SCANWIDTH 320
#define SCANHEIGHT 200
#define SCANSTEP SCANWIDTH-6
#endif /* !_640x400 */
#define COLOR_BLACK 0
#define COLOR_DARK_RED 35
#define COLOR_MEDIUM_RED 36
#define COLOR_LIGHT_RED 37 /* hgr used */
#define COLOR_DARK_GREEN 38
#define COLOR_MEDIUM_GREEN 39
#define COLOR_LIGHT_GREEN 40 /* hgr used */
#define COLOR_DARK_YELLOW 41
#define COLOR_MEDIUM_YELLOW 42
#define COLOR_LIGHT_YELLOW 43
#define COLOR_DARK_BLUE 44
#define COLOR_MEDIUM_BLUE 45
#define COLOR_LIGHT_BLUE 46 /* hgr used */
#define COLOR_DARK_PURPLE 47
#define COLOR_MEDIUM_PURPLE 48
#define COLOR_LIGHT_PURPLE 49 /* hgr used */
#define COLOR_DARK_CYAN 50
#define COLOR_MEDIUM_CYAN 51
#define COLOR_LIGHT_CYAN 52
#define COLOR_DARK_WHITE 53
#define COLOR_MEDIUM_WHITE 54
#define COLOR_LIGHT_WHITE 55
#define COLOR_FLASHING_BLACK 56
#define COLOR_FLASHING_WHITE 57
#define COLOR_FLASHING_UNGREEN 58
#define COLOR_FLASHING_GREEN 59
#ifndef __ASSEMBLER__
/* ----------------------------------
generic graphics globals
---------------------------------- */
/* Pointers to framebuffer (can be VGA memory or host buffer)
*/
extern unsigned char *video__fb1,*video__fb2;
#ifdef _640x400
extern unsigned char video__wider_hires_even[0x1000];
extern unsigned char video__wider_hires_odd[0x1000];
#endif /* _640x400 */
extern unsigned char video__hires_even[0x800];
extern unsigned char video__hires_odd[0x800];
extern unsigned char video__dhires1[256];
extern unsigned char video__dhires2[256];
extern int video__current_page; /* Current visual page */
extern int video__strictcolors;
#ifdef _640x400
extern unsigned char video__wider_int_font[3][0x8000];
#else /* _640x400 */
extern unsigned char video__int_font[3][0x4000];
#endif /* _640x400 */
/* --- Precalculated hi-res page offsets given addr --- */
extern unsigned int video__screen_addresses[8192];
extern unsigned char video__columns[8192];
extern unsigned char video__odd_colors[2];
extern unsigned char video__even_colors[2];
/* Hooks */
void video__write_text0(),
video__write_text0_mixed(),
video__write_text1(),
video__write_text1_mixed(),
video__write_even0(),
video__write_odd0(),
video__write_even0_mixed(),
video__write_odd0_mixed(),
video__write_even1(),
video__write_odd1(),
video__write_even1_mixed(),
video__write_odd1_mixed();
#ifdef APPLE_IIE
void video__write_2e_text0(),
video__write_2e_text0_mixed(),
video__write_2e_text1(),
video__write_2e_text1_mixed(),
video__write_2e_odd0(),
video__write_2e_even0(),
video__write_2e_odd0_mixed(),
video__write_2e_even0_mixed(),
video__write_2e_odd1(),
video__write_2e_even1(),
video__write_2e_odd1_mixed(),
video__write_2e_even1_mixed();
#endif /* APPLE_IIE */
#endif /* !__ASSEMBLER__ */
#endif /* !A2_VIDEO_H */

679
src/vidsup.c Normal file
View File

@ -0,0 +1,679 @@
/*
* Apple // emulator for Linux: Video support
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include "video.h"
#include "cpu.h"
#include "misc.h"
#include "prefs.h"
#ifdef _640x400
unsigned char video__wider_font[0x8000];
#endif /* _640x400 */
unsigned char video__font[0x4000];
/* --- Precalculated hi-res page offsets given addr --- */
unsigned int video__screen_addresses[8192];
unsigned char video__columns[8192];
unsigned char *video__fb1,*video__fb2;
#ifdef _640x400
unsigned char video__wider_hires_even[0x1000];
unsigned char video__wider_hires_odd[0x1000];
#endif
unsigned char video__hires_even[0x800];
unsigned char video__hires_odd[0x800];
unsigned char video__dhires1[256];
unsigned char video__dhires2[256];
/* Interface font:
* (probably could be made static)
*
* Unlike the normal font, only one version is stored, since the interface
* is always displayed in forty columns.
*/
#ifdef _640x400
unsigned char video__wider_int_font[3][0x8000];
#else /* _640x400 */
unsigned char video__int_font[3][0x4000];
#endif /* _640x400 */
int video__current_page; /* Current visual page */
int video__strictcolors;
void video_loadfont(int first,
int quantity,
const unsigned char *data,
int mode)
{
int i,j;
unsigned char x,y,fg,bg;
switch(mode)
{
case 2:
fg = COLOR_BLACK; bg = COLOR_LIGHT_WHITE; break;
case 3:
fg = COLOR_FLASHING_WHITE; bg = COLOR_FLASHING_BLACK; break;
default:
fg = COLOR_LIGHT_WHITE; bg = COLOR_BLACK; break;
}
i = quantity * 8;
while (i--)
{
j = 8;
x = data[i];
while (j--)
{
y = (x & 128) ? fg : bg;
#ifdef _640x400
video__wider_font[(first << 7) + (i << 4) + (j << 1)] =
video__wider_font[(first << 7) + (i << 4) + (j << 1) + 1] =
#endif /* _640x400 */
video__font[(first << 6) + (i << 3) + j] = y;
x <<= 1;
}
}
}
unsigned char video__odd_colors[2] = {COLOR_LIGHT_PURPLE, COLOR_LIGHT_BLUE};
unsigned char video__even_colors[2] = {COLOR_LIGHT_GREEN, COLOR_LIGHT_RED};
/* 40col/80col/lores/hires/dhires line offsets */
unsigned short video__line_offset[24] =
{ 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
0x028, 0x0A8, 0x128, 0x1A8, 0x228, 0x2A8, 0x328, 0x3A8,
0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 };
unsigned char video__dhires1[256] = {
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,
0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0x9,0x9,0xb,0xb,0xd,0xd,0xf,0xf,
0x0,0x1,0x2,0x3,0x6,0x5,0x6,0x7,0xa,0x9,0xa,0xb,0xe,0xd,0xe,0xf,
0x0,0x1,0x3,0x3,0x7,0x5,0x7,0x7,0xb,0x9,0xb,0xb,0xf,0xd,0xf,0xf,
0x0,0x1,0x2,0x3,0x4,0x4,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,
0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0xd,0x9,0xb,0xb,0xd,0xd,0xf,0xf,
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0xe,0x9,0xa,0xb,0xe,0xd,0xe,0xf,
0x0,0x1,0x7,0x3,0x7,0x5,0x7,0x7,0xf,0x9,0xb,0xb,0xf,0xd,0xf,0xf,
};
unsigned char video__dhires2[256] = {
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x8,0x0,0xb,0x8,0xd,0x0,0x0,
0x1,0x1,0x1,0x1,0x0,0x5,0x1,0x1,0x0,0x9,0xb,0xb,0x0,0xd,0xf,0xf,
0x0,0x1,0x2,0x2,0x2,0x5,0x2,0x2,0x0,0xa,0xa,0xa,0xe,0xd,0x2,0x2,
0x3,0x3,0x3,0x3,0x7,0x5,0x7,0x7,0x0,0xb,0xb,0xb,0xf,0xd,0xf,0xf,
0x0,0x0,0x4,0x0,0x4,0x4,0x4,0x4,0xc,0x8,0x4,0x8,0xc,0xd,0x4,0x4,
0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0xd,0x4,0x4,0x4,0xd,0xd,0x4,0x4,
0x6,0x6,0x6,0x2,0xe,0x6,0x6,0x6,0xe,0xe,0xa,0xa,0xe,0x6,0xe,0x6,
0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0xf,0xf,0xb,0xb,0xf,0xf,0xf,0xf,
};
#ifdef APPLE_IIE
/* -------------------------------------------------------------------------
c_initialize_dhires_values()
------------------------------------------------------------------------- */
static void c_initialize_dhires_values(void) {
int i;
/* int value, v; */
/* unsigned char locolor, hicolor; */
/* precalculate the colors for all the 256*8 bit combinations. */
/* for (value = 0x00, v = 0; value <= 0xFF; value++) { */
/* locolor = (value & 0x0F) | 0x10; */
/* hicolor = (value << 4) | 0x10; */
/* dhires_colors[v++] = locolor; */
/* dhires_colors[v++] = locolor; */
/* dhires_colors[v++] = locolor; */
/* dhires_colors[v++] = locolor; */
/* dhires_colors[v++] = hicolor; */
/* dhires_colors[v++] = hicolor; */
/* dhires_colors[v++] = hicolor; */
/* dhires_colors[v++] = hicolor; */
/* } */
for (i = 0; i < 0x80; i++) {
video__dhires1[i+0x80] = video__dhires1[i];
video__dhires2[i+0x80] = video__dhires2[i];
}
}
#endif
/* -------------------------------------------------------------------------
c_initialize_hires_values()
------------------------------------------------------------------------- */
static void c_initialize_hires_values(void)
{
int value, b, v, e, /*color_toggle,*/ last_not_black;
/* precalculate the colors for all the 256*8 bit combinations. */
for (value = 0x00; value <= 0xFF; value++) {
for (e = value * 8, last_not_black = 0, v = value, b = 0;
b < 7; b++, v >>= 1, e++)
{
if (v & 1)
{
video__hires_even[ e ] = last_not_black ?
COLOR_LIGHT_WHITE :
((b & 1) ?
((value & 0x80) ?
COLOR_LIGHT_RED :
COLOR_LIGHT_GREEN) :
((value & 0x80) ?
COLOR_LIGHT_BLUE :
COLOR_LIGHT_PURPLE));
video__hires_odd[ e ] = last_not_black ?
COLOR_LIGHT_WHITE :
((b & 1) ?
((value & 0x80) ?
COLOR_LIGHT_BLUE :
COLOR_LIGHT_PURPLE) :
((value & 0x80) ?
COLOR_LIGHT_RED :
COLOR_LIGHT_GREEN));
if (last_not_black && b > 0)
video__hires_even[ e - 1 ] = COLOR_LIGHT_WHITE,
video__hires_odd[ e - 1 ] = COLOR_LIGHT_WHITE;
last_not_black = 1;
}
else
video__hires_even[ e ] = COLOR_BLACK,
video__hires_odd[ e ] = COLOR_BLACK,
last_not_black = 0;
}
}
if (color_mode == 0) { /* Black and White */
for (value = 0x00; value <= 0xFF; value++) {
for (b = 0, e = value * 8; b < 7; b++, e++) {
if (video__hires_even[ e ] != COLOR_BLACK)
video__hires_even[ e ] = COLOR_LIGHT_WHITE;
if (video__hires_odd[ e ] != COLOR_BLACK)
video__hires_odd[ e ] = COLOR_LIGHT_WHITE;
}
}
}
else if (color_mode == LAZY_INTERP) /* Lazy Interpolated color */
{
for (value = 0x00; value <= 0xFF; value++)
{
for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2)
{
if (video__hires_even[ e ] == COLOR_BLACK &&
video__hires_even[ e - 1 ] != COLOR_BLACK &&
video__hires_even[ e + 1 ] != COLOR_BLACK)
video__hires_even[ e ] =
video__hires_even[ e - 1 ];
if (video__hires_odd[ e ] == COLOR_BLACK &&
video__hires_odd[ e - 1 ] != COLOR_BLACK &&
video__hires_odd[ e + 1 ] != COLOR_BLACK)
video__hires_odd[ e ] =
video__hires_odd[ e - 1 ];
}
for (b = 0, e = value * 8; b <= 6; b += 2, e += 2) {
if (video__hires_odd[ e ] == COLOR_BLACK) {
if (b > 0 && b < 6) {
if (video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e-1];
} else if (b == 0) {
if (video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e+1];
} else {
if (video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE)
video__hires_even[ e ] =
video__hires_even[ e - 1 ];
}
}
if (video__hires_odd[ e ] == COLOR_BLACK) {
if (b > 0 && b < 6) {
if (video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
}
else if (b == 0) {
if (video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e+1];
}
else if
(video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
}
}
}
}
else if (color_mode == INTERP) { /* Color and strict interpolation */
for (value = 0x00; value <= 0xFF; value++) {
for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2) {
if (video__hires_even[e] == COLOR_BLACK) {
if (video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e-1];
else if (
video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e-1];
else if (
video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e+1];
else if (
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
video__hires_even[e] = (value & 0x80)
? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE;
}
if (video__hires_odd[e] == COLOR_BLACK) {
if (video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
else if (
video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
else if (
video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e+1];
else if (
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
video__hires_odd[e] = (value & 0x80)
? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN;
}
}
for (b = 0, e = value * 8; b <= 6; b += 2, e += 2) {
if (video__hires_even[ e ] == COLOR_BLACK) {
if (b > 0 && b < 6) {
if (video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e-1];
else if (
video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e-1];
else if (
video__hires_even[e-1] != COLOR_BLACK &&
video__hires_even[e+1] != COLOR_BLACK &&
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
video__hires_even[e] =
video__hires_even[e+1];
else if (
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
video__hires_even[e] = (value & 0x80)
? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN;
}
}
if (video__hires_odd[e] == COLOR_BLACK) {
if (b > 0 && b < 6) {
if (video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
else if (
video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e-1];
else if (
video__hires_odd[e-1] != COLOR_BLACK &&
video__hires_odd[e+1] != COLOR_BLACK &&
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
video__hires_odd[e] =
video__hires_odd[e+1];
else if (
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
video__hires_odd[e] = (value & 0x80)
? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE;
}
}
}
}
}
#ifdef _640x400
/* *2 for 640x400 */
for (b=0, e=0; b<4096; b++, e++) {
video__wider_hires_even[b] = video__hires_even[e];
video__wider_hires_odd[b] = video__hires_odd[e];
b++;
video__wider_hires_even[b] = video__hires_even[e];
video__wider_hires_odd[b] = video__hires_odd[e];
}
#endif
}
/* -------------------------------------------------------------------------
c_initialize_row_col_tables()
------------------------------------------------------------------------- */
static void c_initialize_row_col_tables(void)
{
int x, y, off, i;
/* hires page offsets. initialize to invalid values. */
for (i = 0; i < 8192; i++) {
(long)(video__screen_addresses[i]) = -1;
}
for (y = 0; y < 24; y++) {
for (off = 0; off < 8; off++) {
for (x = 0; x < 40; x++) {
#ifdef _640x400
video__screen_addresses[video__line_offset[y] + 0x400*off + x ] =
(y*16 + 2*off/* + 8*/) * SCANWIDTH + x*14 + 4;
#else
video__screen_addresses[video__line_offset[y] + 0x400*off + x ] =
(y*8 + off + 4) * 320 + x*7 + 20;
#endif
video__columns[video__line_offset[y] + 0x400*off + x] =
(unsigned char)x;
}
}
}
}
static void c_initialize_tables_video(void) {
int x, y, i;
/* initialize text/lores & hires graphics */
for (y = 0; y < 24; y++) { /* 24 rows */
for (x = 0; x < 40; x++) /* 40 cols */
{
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
/* //e mode: text/lores page 0 */
cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w =
(y < 20) ? video__write_2e_text0 :
video__write_2e_text0_mixed;
}
else
#endif
{
/* ][+ modes: text/lores page 0 */
cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w =
(y < 20) ? video__write_text0 :
video__write_text0_mixed;
}
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w =
(y < 20) ? video__write_2e_text1 :
video__write_2e_text1_mixed;
}
else
#endif
{
/* ][+ modes: text/lores page 1 in main memory */
cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w =
(y < 20) ? video__write_text1 :
video__write_text1_mixed;
}
for (i = 0; i < 8; i++)
{
/* //e mode: hires/double hires page 0 */
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[ 0x2000 + video__line_offset[ y ]
+ 0x400 * i + x ].w =
(y < 20) ? ((x & 1) ? video__write_2e_odd0 :
video__write_2e_even0)
: ((x & 1) ? video__write_2e_odd0_mixed :
video__write_2e_even0_mixed);
}
/* ][+ modes: hires page 0 */
else
#endif
{
cpu65_vmem[ 0x2000 + video__line_offset[ y ]
+ 0x400 * i + x ].w =
(y < 20) ? ((x & 1) ? video__write_odd0 :
video__write_even0)
: ((x & 1) ? video__write_odd0_mixed :
video__write_even0_mixed);
}
#ifdef APPLE_IIE
if (apple_mode == IIE_MODE) {
cpu65_vmem[ 0x4000 + video__line_offset[ y ]
+ 0x400 * i + x ].w =
(y < 20) ? ((x & 1) ? video__write_2e_odd1 :
video__write_2e_even1)
: ((x & 1) ? video__write_2e_odd1_mixed :
video__write_2e_even1_mixed);
}
/* ][+ modes: hires page 1 */
else
#endif
{
cpu65_vmem[ 0x4000 + video__line_offset[ y ]
+ 0x400 * i + x ].w =
(y < 20) ? ((x & 1) ? video__write_odd1 :
video__write_even1)
: ((x & 1) ? video__write_odd1_mixed :
video__write_even1_mixed);
}
}
}
}
}
void video_set(int flags)
{
if (color_mode == COLOR)
video__strictcolors = 1; /* strict colors */
else if (color_mode == INTERP)
video__strictcolors = 2; /* strict interpolation */
else
video__strictcolors = 0; /* lazy coloration */
c_initialize_hires_values(); /* precalculate hires values */
c_initialize_row_col_tables(); /* precalculate hires offsets */
c_initialize_tables_video(); /* memory jump tables for video */
#ifdef APPLE_IIE
c_initialize_dhires_values(); /* set up dhires colors */
#endif
}
void video_loadfont_int(int first, int quantity, const unsigned char *data)
{
int i,j;
unsigned char x;
int y;
i = quantity * 8;
while (i--)
{
j = 8;
x = data[i];
while (j--)
{
#ifdef _640x400
y = (first << 7) + (i << 4) + (j << 1);
if (x & 128)
{
video__wider_int_font[0][y] =
video__wider_int_font[0][y+1] =
video__wider_int_font[1][y] =
video__wider_int_font[1][y+1] = COLOR_LIGHT_GREEN;
video__wider_int_font[2][y] =
video__wider_int_font[2][y+1] = COLOR_LIGHT_RED;
}
else
{
video__wider_int_font[0][y] =
video__wider_int_font[0][y+1] =
video__wider_int_font[2][y] =
video__wider_int_font[2][y+1] = COLOR_BLACK;
video__wider_int_font[1][y] =
video__wider_int_font[1][y+1] = COLOR_MEDIUM_BLUE;
}
#else
y = (first << 6) + (i << 3) + j;
if (x & 128)
{
video__int_font[0][y] =
video__int_font[1][y] = COLOR_LIGHT_GREEN;
video__int_font[2][y] = COLOR_LIGHT_RED;
}
else
{
video__int_font[0][y] =
video__int_font[2][y] = COLOR_BLACK;
video__int_font[1][y] = COLOR_MEDIUM_BLUE;
}
#endif /* _640x400 */
x <<= 1;
}
}
}
/* Should probably move this to assembly... */
static void c_interface_print_char40_line(
unsigned char **d, unsigned char **s)
{
#ifdef _640x400
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/
*d += SCANSTEP, *s -= 12;
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/
*d += SCANSTEP, *s += 4;
#else
*((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/
*d += 4, *s += 4;
*((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/
*d += 2, *s += 2;
*((unsigned char *)(*d)) = *((unsigned char *)(*s));/*8bits*/
*d += SCANSTEP, *s += 2;
#endif
}
void video_plotchar( int x, int y, int scheme, unsigned char c )
{
int off;
unsigned char *d;
unsigned char *s;
#ifdef _640x400
off = y * SCANWIDTH * 16 + x * 14 + 4;
s = video__wider_int_font[scheme] + c * 128;
#else
off = y * 320 * 8 + x * 7 + 1300;
s = video__int_font[scheme] + c * 64;
#endif
d = video__fb1 + off;
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
c_interface_print_char40_line(&d,&s);
}

851
src/xvideo.c Normal file
View File

@ -0,0 +1,851 @@
/*
* Apple // emulator for Linux: X-Windows graphics support
*
* Copyright 1994 Alexander Jean-Claude Bottema
* Copyright 1995 Stephen Lee
* Copyright 1997, 1998 Aaron Culliney
* Copyright 1998, 1999, 2000 Michael Deutschmann
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>/* MITSHM! */
#include "video.h"
#include "misc.h"
#include "keys.h"
/* copied from svideo.c (didn't bother to rename!) */
static unsigned char *svga_GM;
static unsigned char vga_mem_page_0[SCANWIDTH*SCANHEIGHT]; /* page0 framebuffer */
static unsigned char vga_mem_page_1[SCANWIDTH*SCANHEIGHT]; /* page1 framebuffer */
static Display *display;
static Window win;
static GC gc;
static unsigned int width, height; /* window size */
static int screen_num;
static Visual* visual;
static XVisualInfo visualinfo;
static XColor colors[256];
XImage *image;
static Colormap cmap;
XEvent xevent;
int doShm = 1;/* assume true */
XShmSegmentInfo xshminfo;
int xshmeventtype;
/* -------------------------------------------------------------------------
video_setpage(p): Switch to screen page p
------------------------------------------------------------------------- */
void video_setpage(int p)
{
if (p == video__current_page) return;
if (p)
{
memcpy(vga_mem_page_0,svga_GM,SCANWIDTH*SCANHEIGHT);
memcpy(svga_GM,vga_mem_page_1,SCANWIDTH*SCANHEIGHT);
video__current_page = 1;
video__fb1 = vga_mem_page_0;
video__fb2 = svga_GM;
}
else
{
memcpy(vga_mem_page_1,svga_GM,SCANWIDTH*SCANHEIGHT);
memcpy(svga_GM,vga_mem_page_0,SCANWIDTH*SCANHEIGHT);
video__current_page = 0;
video__fb1 = svga_GM;
video__fb2 = vga_mem_page_1;
}
}
/*
* XShm code influenced from the DOOM source code.
* This tries to find some shared memory to use. It checks for stale segments
* (maybe due to an emulator crash) and tries to remove them or use them.
*/
static void getshm(int size) {
int key = ('a'<<24) | ('p'<<16) | ('p'<<8) | 'l';
struct shmid_ds shminfo;
int id;
int rc;
int counter=5;
/* Try to allocate shared memory segment. Use stale segments if any are
* found.
*/
do
{
id = shmget((key_t) key, 0, 0777);
if (id != -1)
{
/* we got someone else's ID. check if it's stale. */
printf("Found shared memory key=`%c%c%c%c', id=%d\n",
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id
);
rc=shmctl(id, IPC_STAT, &shminfo); /* get stats */
if (!rc) {
/* someone's using the emulator */
if (shminfo.shm_nattch) {
printf( "User uid=%d, key=`%c%c%c%c' appears to be running "
"the emulator.\n",
shminfo.shm_perm.cuid,
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff)
);
++key; /* increase the key count */
}
/* found a stale ID. */
else {
/* it's my stale ID */
if (getuid() == shminfo.shm_perm.cuid) {
rc = shmctl(id, IPC_RMID, 0);
if (!rc)
printf("Was able to kill my old shared memory\n");
else {
perror("shmctl");
printf("Was NOT able to kill my old shared memory\n");
}
id = shmget((key_t)key, size, IPC_CREAT|0777);
if (id == -1) {
perror("shmget");
printf("Could not get shared memory\n");
}
rc=shmctl(id, IPC_STAT, &shminfo);
if (rc) {
perror("shmctl");
}
break;
}
/* not my ID, but maybe we can use it */
if (size == shminfo.shm_segsz) {
printf( "Will use stale shared memory of uid=%d\n",
shminfo.shm_perm.cuid);
break;
}
/* not my ID, and we can't use it */
else {
printf( "Can't use stale shared memory belonging to uid=%d, "
"key=`%c%c%c%c', id=%d\n",
shminfo.shm_perm.cuid,
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id
);
++key;
}
}
}
else
{
/* oops. what to do now? */
perror("shmctl");
printf( "Could not get stats on key=`%c%c%c%c', id=%d\n",
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id
);
++key;
}
}
else
{
/* no stale ID's */
id = shmget((key_t)key, size, IPC_CREAT|0777);
if (id == -1) {
perror("shmget");
printf("Could not get shared memory\n");
++key;
}
break;
}
} while (--counter);
if (!counter)
{
printf( "System has too many stale/used "
"shared memory segments!\n");
}
xshminfo.shmid = id;
/* attach to the shared memory segment */
image->data = xshminfo.shmaddr = shmat(id, 0, 0);
if (image->data == -1) {
perror("shmat");
printf("Could not attach to shared memory\n");
exit(1);
}
printf( "Using shared memory key=`%c%c%c%c', id=%d, addr=0x%x\n",
(key & 0xff000000)>>24,
(key & 0xff0000)>>16,
(key & 0xff00)>>8,
(key & 0xff),
id,
(int) (image->data));
}
static void c_initialize_colors() {
static unsigned char col2[ 3 ] = {255,255,255};
static int firstcall = 1;
int c,i,j;
if (visualinfo.class == PseudoColor && visualinfo.depth == 8)
{
/* initialize the colormap */
if (firstcall) {
firstcall = 0;
for (i=0; i<256; i++) {
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
}
}
/* align the palette for hires graphics */
for (i = 0; i < 8; i++) {
for (j = 0; j < 3; j++) {
c = (i & 1) ? col2[ j ] : 0;
colors[ j+i*3+32].red = (c<<8) + c;
c = (i & 2) ? col2[ j ] : 0;
colors[ j+i*3+32].green = (c<<8) + c;
c = (i & 4) ? col2[ j ] : 0;
colors[ j+i*3+32].blue = (c<<8) + c;
}
}
colors[ COLOR_FLASHING_BLACK].red = 0;
colors[ COLOR_FLASHING_BLACK].green = 0;
colors[ COLOR_FLASHING_BLACK].blue = 0;
colors[ COLOR_LIGHT_WHITE].red = (255<<8)|255;
colors[ COLOR_LIGHT_WHITE].green = (255<<8)|255;
colors[ COLOR_LIGHT_WHITE].blue = (255<<8)|255;
colors[ COLOR_FLASHING_WHITE].red = (255<<8)|255;
colors[ COLOR_FLASHING_WHITE].green = (255<<8)|255;
colors[ COLOR_FLASHING_WHITE].blue = (255<<8)|255;
colors[0x00].red = 0; colors[0x00].green = 0;
colors[0x00].blue = 0; /* Black */
colors[0x10].red = 195; colors[0x10].green = 0;
colors[0x10].blue = 48; /* Magenta */
colors[0x20].red = 0; colors[0x20].green = 0;
colors[0x20].blue = 130; /* Dark Blue */
colors[0x30].red = 166; colors[0x30].green = 52;
colors[0x30].blue = 170; /* Purple */
colors[0x40].red = 0; colors[0x40].green = 146;
colors[0x40].blue = 0; /* Dark Green */
colors[0x50].red = 105; colors[0x50].green = 105;
colors[0x50].blue = 105; /* Dark Grey*/
colors[0x60].red = 113; colors[0x60].green = 24;
colors[0x60].blue = 255; /* Medium Blue */
colors[0x70].red = 12; colors[0x70].green = 190;
colors[0x70].blue = 235; /* Light Blue */
colors[0x80].red = 150; colors[0x80].green = 85;
colors[0x80].blue = 40; /* Brown */
colors[0x90].red = 255; colors[0xa0].green = 24;
colors[0x90].blue = 44; /* Orange */
colors[0xa0].red = 150; colors[0xa0].green = 170;
colors[0xa0].blue = 170; /* Light Gray */
colors[0xb0].red = 255; colors[0xb0].green = 158;
colors[0xb0].blue = 150; /* Pink */
colors[0xc0].red = 0; colors[0xc0].green = 255;
colors[0xc0].blue = 0; /* Green */
colors[0xd0].red = 255; colors[0xd0].green = 255;
colors[0xd0].blue = 0; /* Yellow */
colors[0xe0].red = 130; colors[0xe0].green = 255;
colors[0xe0].blue = 130; /* Aqua */
colors[0xf0].red = 255; colors[0xf0].green = 255;
colors[0xf0].blue = 255; /* White */
/* mirror of lores colors optimized for dhires code */
colors[0x00].red = 0; colors[0x00].green = 0;
colors[0x00].blue = 0; /* Black */
colors[0x08].red = 195; colors[0x08].green = 0;
colors[0x08].blue = 48; /* Magenta */
colors[0x01].red = 0; colors[0x01].green = 0;
colors[0x01].blue = 130; /* Dark Blue */
colors[0x09].red = 166; colors[0x09].green = 52;
colors[0x09].blue = 170; /* Purple */
colors[0x02].red = 0; colors[0x02].green = 146;
colors[0x02].blue = 0; /* Dark Green */
colors[0x0a].red = 105; colors[0x0A].green = 105;
colors[0x0a].blue = 105; /* Dark Grey*/
colors[0x03].red = 113; colors[0x03].green = 24;
colors[0x03].blue = 255; /* Medium Blue */
colors[0x0b].red = 12; colors[0x0b].green = 190;
colors[0x0b].blue = 235; /* Light Blue */
colors[0x04].red = 150; colors[0x04].green = 85;
colors[0x04].blue = 40; /* Brown */
colors[0x0c].red = 255; colors[0x0c].green = 24;
colors[0x0c].blue = 44; /* Orange */
colors[0x05].red = 150; colors[0x05].green = 170;
colors[0x05].blue = 170; /* Light Gray */
colors[0x0d].red = 255; colors[0x0d].green = 158;
colors[0x0d].blue = 150; /* Pink */
colors[0x06].red = 0; colors[0x06].green = 255;
colors[0x06].blue = 0; /* Green */
colors[0x0e].red = 255; colors[0x0e].green = 255;
colors[0x0e].blue = 0; /* Yellow */
colors[0x07].red = 130; colors[0x07].green = 255;
colors[0x07].blue = 130; /* Aqua */
colors[0x0f].red = 255; colors[0x0f].green = 255;
colors[0x0f].blue = 255; /* White */
for (i=0; i<16; i++) {
colors[i].red = (colors[i].red<<8) | colors[i].red;
colors[i].green = (colors[i].green<<8) | colors[i].green;
colors[i].blue = (colors[i].blue<<8) | colors[i].blue;
colors[i<<4].red = (colors[i<<4].red<<8) | colors[i<<4].red;
colors[i<<4].green = (colors[i<<4].green<<8) | colors[i<<4].green;
colors[i<<4].blue = (colors[i<<4].blue<<8) | colors[i<<4].blue;
}
// store the colors to the current colormap
XStoreColors(display, cmap, colors, 256);
}
}
/* HACK: this is incredibly broken.
* Map the X keysyms back into scancodes so the routines in keys.c can deal
* with it. We do this to be compatible with what the SVGAlib version does.
*/
static int keysym_to_scancode(void) {
static int rc = 0xFF;
switch(rc = XKeycodeToKeysym(display, xevent.xkey.keycode, 0))
{
case XK_F1:
rc = 59; break;
case XK_F2:
rc = 60; break;
case XK_F3:
rc = 61; break;
case XK_F4:
rc = 62; break;
case XK_F5:
rc = 63; break;
case XK_F6:
rc = 64; break;
case XK_F7:
rc = 65; break;
case XK_F8:
rc = 66; break;
case XK_F9:
rc = 67; break;
case XK_F10:
rc = 68; break;
case XK_Left:
rc = 105; break;
case XK_Right:
rc = 106; break;
case XK_Down:
rc = 108; break;
case XK_Up:
rc = 103; break;
case XK_Escape:
rc = 1; break;
case XK_Return:
rc = 28; break;
case XK_Tab:
rc = 15; break;
case XK_Shift_L:
rc = SCODE_L_SHIFT; break;
case XK_Shift_R:
rc = SCODE_R_SHIFT; break;
case XK_Control_L:
rc = SCODE_L_CTRL; break;
case XK_Control_R:
rc = SCODE_R_CTRL; break;
case XK_Caps_Lock:
rc = SCODE_CAPS; break;
case XK_BackSpace:
rc = 14; break;
case XK_Insert:
rc = 110; break;
case XK_Pause:
rc = 119; break;
case XK_Break:
/* Pause and Break are the same key, but have different
* scancodes (on PC keyboards). Ctrl makes the difference.
*
* We assume the X server is passing along the distinction to us,
* rather than making us check Ctrl manually.
*/
rc = 101; break;
case XK_Print:
rc = 99; break;
case XK_Delete:
rc = 111; break;
case XK_End:
rc = 107; break;
case XK_Home:
rc = 102; break;
case XK_Page_Down:
rc = 109; break;
case XK_Page_Up:
rc = 104; break;
// keypad joystick movement
case XK_KP_5:
case XK_KP_Begin:
rc = SCODE_J_C; break;
case XK_KP_4:
case XK_KP_Left:
rc = SCODE_J_L; break;
case XK_KP_8:
case XK_KP_Up:
rc = SCODE_J_U; break;
case XK_KP_6:
case XK_KP_Right:
rc = SCODE_J_R; break;
case XK_KP_2:
case XK_KP_Down:
rc = SCODE_J_D; break;
case XK_Alt_L:
rc = 56; break;
case XK_Alt_R:
rc = 100; break;
default:
if ((rc >= XK_space) && (rc <= XK_asciitilde))
rc = xevent.xkey.keycode - 8;
break;
}
return rc & 0xFF;/* normalize */
}
static void post_image() {
if (doShm) {
if (!XShmPutImage(
display,
win,
gc,
image,
0, 0,
0, 0,
SCANWIDTH, SCANHEIGHT,
True))
fprintf(stderr, "XShmPutImage() failed\n");
} else {
if (XPutImage(
display,
win,
gc,
image,
0, 0,
0, 0,
SCANWIDTH, SCANHEIGHT
))
fprintf(stderr, "XPutImage() failed\n");
}
}
static void c_flash_cursor(int on) {
// flash only if it's text or mixed modes.
if (softswitches & (SS_TEXT|SS_MIXED)) {
if (!on) {
colors[ COLOR_FLASHING_BLACK].red = 0;
colors[ COLOR_FLASHING_BLACK].green = 0;
colors[ COLOR_FLASHING_BLACK].blue = 0;
colors[ COLOR_FLASHING_WHITE].red = 0xffff;
colors[ COLOR_FLASHING_WHITE].green = 0xffff;
colors[ COLOR_FLASHING_WHITE].blue = 0xffff;
} else {
colors[ COLOR_FLASHING_WHITE].red = 0;
colors[ COLOR_FLASHING_WHITE].green = 0;
colors[ COLOR_FLASHING_WHITE].blue = 0;
colors[ COLOR_FLASHING_BLACK].red = 0xffff;
colors[ COLOR_FLASHING_BLACK].green = 0xffff;
colors[ COLOR_FLASHING_BLACK].blue = 0xffff;
}
// store the colors to the current colormap
XStoreColors(display, cmap, colors, 256);
}
}
/* FIXME: blocking not implemented... */
void video_sync(int block) {
static int flash_count = 0;
// post the image and loop waiting for it to finish and
// also process other input events
post_image();
LOOP:
if (doShm)
XNextEvent(
display,
&xevent);
else if (!XCheckMaskEvent(
display,
KeyPressMask|KeyReleaseMask,
&xevent))
goto POLL_FINISHED;
switch (xevent.type) {
case KeyPress:
c_read_raw_key(keysym_to_scancode(), 1);
break;
case KeyRelease:
c_read_raw_key(keysym_to_scancode(), 0);
break;
default:
if (xevent.type == xshmeventtype)
goto POLL_FINISHED;
break;
}
goto LOOP;
POLL_FINISHED:
switch (++flash_count)
{
case 6:
c_flash_cursor(1);
break;
case 12:
c_flash_cursor(0);
flash_count = 0;
break;
default:
break;
}
}
static Cursor hidecursor() {
Pixmap cursormask;
XGCValues xgc;
XColor dummycolour;
Cursor cursor;
cursormask = XCreatePixmap(display, win, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
static void parseArgs() {
int i;
for (i=0; i<argc; i++) {
if (strstr(argv[i], "-noshm"))
doShm=0;
}
}
void video_init() {
XSetWindowAttributes attribs;
unsigned long attribmask;
int x, y; /* window position */
int drawingok;
unsigned int display_width, display_height;
XGCValues xgcvalues;
int valuemask;
char *window_name = "Apple ][";
char *icon_name = window_name;
XSizeHints *size_hints;
XWMHints *wm_hints;
XClassHint *class_hints;
XTextProperty windowName, iconName;
GC gc;
char *progname;/* name this program was invoked by */
char *displayname = NULL;
progname = argv[0];
/* give up root privileges. equivalent of vga_init() */
setegid(getgid());
seteuid(getuid());
parseArgs();
if (!(size_hints = XAllocSizeHints())) {
fprintf(stderr, "cannot allocate memory for SizeHints\n");
exit(1);
}
if (!(wm_hints = XAllocWMHints())) {
fprintf(stderr, "cannot allocate memory for WMHints\n");
exit(1);
}
if (!(class_hints = XAllocClassHint())) {
fprintf(stderr, "cannot allocate memory for ClassHints\n");
exit(1);
}
/* connect to X server */
if ( (display=XOpenDisplay(displayname)) == NULL )
{
fprintf(stderr, "cannot connect to X server \"%s\"\n",
XDisplayName(displayname));
exit(1);
}
/* get screen size from display structure macro */
screen_num = DefaultScreen(display);
if (!XMatchVisualInfo(display, screen_num, 8, PseudoColor, &visualinfo)) {
fprintf(stderr,
"Sorry bud, xapple2 only supports "
"8bit PseudoColor displays.\n"
"Maybe you can fix this!\n");
exit(1);
}
visual = visualinfo.visual;
display_width = DisplayWidth(display, screen_num);
display_height = DisplayHeight(display, screen_num);
/* Note that in a real application, x and y would default to 0
* but would be settable from the command line or resource database.
*/
x = y = 0;
width = SCANWIDTH, height = SCANHEIGHT;
/* init MITSHM if we're doing it */
if (doShm) {
/* make sure we have it */
doShm = XShmQueryExtension(display);
/* and it's a local connection */
if (!displayname)
displayname = getenv("DISPLAY");
if (displayname)
{
if ((*displayname != ':') || !doShm) {
printf("Cannot run MITSHM version of emulator "
"with display \"%s\"\n"
"Try something like \":0.0\". "
"Reverting to regular X with no sound.\n",
displayname);
doShm = 0;
soundAllowed=0;
c_initialize_sound();
}
}
} else {
/* and it's a local connection */
if (!displayname)
displayname = getenv("DISPLAY");
if (displayname)
{
if (*displayname != ':') {
printf("Sound not allowed for remote display \"%s\".\n",
displayname);
soundAllowed=0;
c_initialize_sound();
}
}
}
/* initialize colors */
cmap = XCreateColormap(display, RootWindow(display, screen_num),
visual, AllocAll);
c_initialize_colors();
attribs.colormap = cmap;
attribs.border_pixel = 0;
/* select event types wanted */
attribmask = CWEventMask | CWColormap | CWBorderPixel;/* HACK CWBorderPixel? */
attribs.event_mask =
KeyPressMask
| KeyReleaseMask
| ExposureMask;
/* create opaque window */
win = XCreateWindow(display, RootWindow(display,screen_num),
x, y, width, height,
0,/* border_width */
8,/* depth */
InputOutput,
visual,
attribmask,
&attribs);
/* set size hints for window manager. We don't want the user to
* dynamically allocate window size since we won't do the right
* scaling in response. Whaddya want, performance or a snazzy gui?
*/
size_hints->flags = PPosition | PSize | PMinSize | PMaxSize;
size_hints->min_width = width;
size_hints->min_height = height;
size_hints->max_width = width;
size_hints->max_height = height;
/* store window_name and icon_name for niceity. */
if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) {
fprintf(stderr, "structure allocation for windowName failed.\n");
exit(1);
}
if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) {
fprintf(stderr, "structure allocation for iconName failed.\n");
exit(1);
}
wm_hints->initial_state = NormalState;
wm_hints->input = True;
wm_hints->flags = StateHint | IconPixmapHint/* | InputHint*/;
class_hints->res_name = progname;
class_hints->res_class = "Apple2";
XSetWMProperties(display, win, &windowName, &iconName,
argv, argc, size_hints, wm_hints,
class_hints);
XDefineCursor(display, win, hidecursor(display, win));
/* create the GC */
valuemask = GCGraphicsExposures;
xgcvalues.graphics_exposures = False;
gc = XCreateGC(
display,
win,
valuemask,
&xgcvalues);
/* display window */
XMapWindow(display, win);
/* wait until it is OK to draw */
drawingok = 0;
while (!drawingok)
{
XNextEvent(display, &xevent);
if ((xevent.type == Expose) && !xevent.xexpose.count)
{
drawingok = 1;
}
}
xshmeventtype = XShmGetEventBase(display) + ShmCompletion;
/* create the image */
if (doShm) {
image = XShmCreateImage(
display,
visual,
8,
ZPixmap,
0,
&xshminfo,
SCANWIDTH,
SCANHEIGHT);
if (!image) {
fprintf(stderr, "XShmCreateImage failed\n");
exit(1);
}
printf("Allocating shared memory %dx%d region\n",
image->bytes_per_line, image->height);
getshm(image->bytes_per_line * image->height);
/* get the X server to attach to it */
if (!XShmAttach(display, &xshminfo)) {
fprintf(stderr, "XShmAttach() failed in InitGraphics()\n");
exit(1);
}
} else {
char *data = malloc(SCANWIDTH*SCANHEIGHT*sizeof(unsigned char));
if (!data) {
fprintf(stderr, "no memory for image data!\n");
exit(1);
}
printf("Creating regular XImage\n");
image = XCreateImage(
display,
visual,
8,
ZPixmap,
0,
data,
SCANWIDTH,
SCANHEIGHT,
8/*bitmap_pad*/,
SCANWIDTH/*bytes_per_line*/);
if (!image) {
fprintf(stderr, "XCreateImage failed\n");
exit(1);
}
}
svga_GM = video__fb1 = image->data;
video__fb2 = vga_mem_page_1;
memset(video__fb1,0,SCANWIDTH*SCANHEIGHT);
memset(video__fb2,0,SCANWIDTH*SCANHEIGHT);
}
void video_shutdown(void)
{
if (doShm) {
// Detach from X server
if (!XShmDetach(display, &xshminfo))
fprintf(stderr,"XShmDetach() failed in video_shutdown()\n");
// Release shared memory.
shmdt(xshminfo.shmaddr);
shmctl(xshminfo.shmid, IPC_RMID, 0);
// Paranoia.
image->data = NULL;
} else {
free(image->data);
}
exit(0);
}