Updated Atari800 project (by Lubomyr)

This commit is contained in:
pelya
2011-02-04 10:58:55 +00:00
parent 9e8f4d794c
commit e99f38c873
105 changed files with 118 additions and 64789 deletions

View File

@@ -1,26 +1,34 @@
# The application settings for Android libSDL port
AppSettingVersion=9
AppSettingVersion=16
LibSdlVersion=1.2
AppName="Atari800 emulator"
AppName="Atari800"
AppFullName=net.sourceforge.atari800
ScreenOrientation=h
AppDataDownloadUrl="Download Atari ROM, note that it is ILLEGAL to download it without owning Atari device!|https://sites.google.com/site/xpelyax/Home/atari800.zip?attredirects=0&d=1"
InhibitSuspend=n
AppDataDownloadUrl="Download Atari ROM, note that it is ILLEGAL to download it without owning Atari device!|atari800-data.zip"
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
AppUsesMouse=n
AppNeedsTwoButtonMouse=n
AppNeedsArrowKeys=y
AppNeedsTextInput=y
AppUsesJoystick=n
AppHandlesJoystickSensitivity=y
AppUsesMultitouch=n
NonBlockingSwapBuffers=n
RedefinedKeys="RETURN SPACE KP_PLUS KP_MINUS F1 ESCAPE F2 F3"
RedefinedKeys="F6 RETURN F4 F3 F1 ESCAPE F6 F3 F4 F2 F6"
AppTouchscreenKeyboardKeysAmount=6
AppTouchscreenKeyboardKeysAmountAutoFire=2
RedefinedKeysScreenKb="F6 F1 RETURN F4 F3 F2"
MultiABI=n
AppVersionCode=21001
AppVersionName="2.1.0.01"
CompiledLibraries="sdl_mixer png"
CustomBuildScript=n
AppCflags='-O2 -finline-functions -DSOUND'
AppVersionCode=21003
AppVersionName="2.2.0rc2.02"
CompiledLibraries="jpeg png"
CustomBuildScript=y
AppCflags=''
AppLdflags=''
AppSubdirsBuild=''
AppUseCrystaXToolchain=n
AppCmdline='-audio16'
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

View File

@@ -0,0 +1,17 @@
#!/bin/sh
LOCAL_PATH=`dirname $0`
LOCAL_PATH=`cd $LOCAL_PATH && pwd`
ln -sf libsdl-1.2.so $LOCAL_PATH/../../../obj/local/armeabi/libSDL.so
if [ \! -f atari800/configure ] ; then
sh -c "cd atari800/src && ./autogen.sh"
fi
if [ \! -f atari800/src/Makefile ] ; then
../setEnvironment.sh sh -c "cd atari800/src && ./configure --build=x86_64-unknown-linux-gnu --host=arm-linux-androideabi --target=sdl --without-x"
fi
make -C atari800/src && mv -f atari800/src/atari800 libapplication.so

View File

@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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
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) <year> <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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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) year 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.

View File

@@ -1,34 +0,0 @@
Atari800 emulator version 2.1.0
-------------------------------
This is free and portable Atari800/XL/XE/5200 emulator, originally written
by David Firth and now developed by the Atari800 Development Team (please
see DOC/CREDITS). This program is copyrighted and released under the GPL
(see COPYING).
Please read DOC/README, DOC/INSTALL and DOC/USAGE.
For news in this release please do read DOC/NEWS.
If you have a problem running this emulator please read DOC/FAQ first.
If the problem persists then please ask in newsgroup comp.sys.atari.8bit
or in the atari800-users mailing list (see below).
Look at DOC/BUGS before reporting something you consider a bug.
If you want to help developing Atari800 emulator you can subscribe to our
mailing list (http://lists.sourceforge.net/lists/listinfo/atari800-users).
DOC/TODO might point you in the right direction.
This version, and all versions back to 0.8.2 have been released by me (Petr
Stehlik) and are now available at Sourceforge.net (URL below). Thanks
go to David Firth and all the people that helped making this release.
EnJoy!
Petr Stehlik
March 27, 2009
E-mail: pstehlik@sophics.cz
Project homepage: http://atari800.sourceforge.net/

View File

@@ -0,0 +1 @@
/home/lubomyr/atari800/atari800

View File

@@ -0,0 +1,71 @@
Only in atari800/atari800/src: config.h.in
diff -ru orig/atari800/atari800/src/config.sub atari800/atari800/src/config.sub
--- orig/atari800/atari800/src/config.sub 2006-04-08 08:07:36.000000000 -0400
+++ atari800/atari800/src/config.sub 2011-02-03 10:28:16.000000000 -0500
@@ -1206,7 +1206,7 @@
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -udi* | -eabi* | -androideabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
diff -ru orig/atari800/atari800/src/configure.ac atari800/atari800/src/configure.ac
--- orig/atari800/atari800/src/configure.ac 2010-12-07 10:16:26.000000000 -0500
+++ atari800/atari800/src/configure.ac 2011-02-03 10:45:32.000000000 -0500
@@ -97,7 +97,7 @@
AC_DEFINE(DOS_DRIVES,1,[Define to enable DOS style drives support.])
AC_DEFINE(SYSTEM_WIDE_CFG_FILE,"c:\\atari800.cfg",[Alternate system-wide config file for non-Unix OS.])
;;
- linux | linux-gnu)
+ linux | linux-gnu | androideabi)
a8_host="linux"
;;
mint)
@@ -301,7 +301,7 @@
WANT_NTSC_FILTER=yes
LIBS="$LIBS `sdl-config --libs`"
OBJS="videomode.o sdl/main.o sdl/video.o sdl/video_sw.o sdl/input.o sdl/palette.o"
- CFLAGS="$CFLAGS -ansi -pedantic -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Winline"
+ CFLAGS="$CFLAGS -O3 -pedantic -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Winline"
if [[ "$a8_host" != "beos" ]]; then
dnl BeOS has a real issue with redundant-decls
CFLAGS="$CFLAGS -Wredundant-decls"
Only in atari800/atari800/src: configure.ac~
diff -ru orig/atari800/atari800/src/sdl/input.c atari800/atari800/src/sdl/input.c
--- orig/atari800/atari800/src/sdl/input.c 2010-12-07 10:16:26.000000000 -0500
+++ atari800/atari800/src/sdl/input.c 2011-02-03 10:46:35.000000000 -0500
@@ -22,9 +22,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef ANDROID
#ifdef __linux__
#define LPTJOY 1
#endif
+#endif
#ifdef LPTJOY
#include <fcntl.h>
@@ -1214,6 +1216,9 @@
int stick0, stick1;
stick0 = stick1 = INPUT_STICK_CENTRE;
+ if( !kbhits )
+ return;
+
if (PLATFORM_kbd_joy_0_enabled) {
if (kbhits[KBD_STICK_0_LEFT])
stick0 = INPUT_STICK_LEFT;
@@ -1281,6 +1286,9 @@
int trig0, trig1, i;
trig0 = trig1 = 1;
+ if( !kbhits )
+ return;
+
if (PLATFORM_kbd_joy_0_enabled) {
trig0 = kbhits[KBD_TRIG_0] ? 0 : 1;
}
Only in atari800/atari800/src/sdl: input.c~

View File

@@ -1,820 +0,0 @@
.TH ATARI800 1 "March 26, 2009"
.SH NAME
atari800 \- Atari 800 Emulator, Version 2.1.0
.SH SYNOPSIS
\fBatari800\fP [options] [files...]
.SH DESCRIPTION
\fIatari800\fP emulates the Atari 800, Atari 800 XL, Atari 130 XE and
Atari 5200 Games System.
.SS Options
.TP
\fB-help
Print complete and up-to-date list of command line switches
.TP
\fB-v
Print emulator version
.TP
\fB-verbose
Display framerate when exiting
.TP
\fB-config filename
Specify an alternative configuration filename
.TP
\fB-osa_rom filename
Path to file containing Atari Rev.A Operating System.
Used to override paths defined at compile time.
.TP
\fB-osb_rom filename
Path to file containing Atari Rev.B Operating System.
Used to override paths defined at compile time.
.TP
\fB-xlxe_rom filename
Path to file containing Atari XL/XE Operating System.
Used to override paths defined at compile time.
.TP
\fB-5200_rom filename
Path to file containing Atari 5200 Games System ROM.
Used to override paths defined at compile time.
.TP
\fB-basic_rom filename
Path to file containing Atari BASIC ROM.
Used to override paths defined at compile time.
.TP
\fB-atari
Emulate Atari 800
.TP
\fB-xl
Emulate Atari 800 XL
.TP
\fB-xe
Emulate Atari 130 XE
.TP
\fB-320xe
Emulate Atari 320 XE (Compy Shop)
.TP
\fB-rambo
Emulate Atari 320 XE (Rambo)
.TP
\fB-5200
Emulate Atari 5200
.TP
\fB-emuos
Use EmuOS
.TP
\fB-a
Use Atari OS/A for Atari 800
.TP
\fB-b
Use Atari OS/B for Atari 800
.TP
\fB-c
Enable RAM between 0xc000 and 0xcfff in Atari 800
.TP
\fB-axlon <n>
Use Atari 800 Axlon memory expansion: <n> k total RAM
.TP
\fB-axlon0f
Use Axlon shadow at 0x0fc0-0x0fff
.TP
\fB-mosaic <n>
Use 400/800 Mosaic memory expansion: <n> k total RAM
.TP
\fB-pal
Emulate PAL TV mode
.TP
\fB-ntsc
Emulate NTSC TV mode
.TP
\fB-nobasic
Used to disable Basic when starting the emulator in XL/XE mode.
Simulates the Option key being held down during system boot.
.TP
\fB-basic
Turn on Atari BASIC ROM
.TP
\fB-cart <filename>
Insert cartridge (CART or raw format)
.TP
\fB-run <filename>
Run Atari program (EXE, COM, XEX, BAS, LST)
.TP
\fB-state <filename>
Load saved-state file
.TP
\fB-tape <filename>
Attach cassette image (CAS format or raw file)
.TP
\fB-boottape <filename>
Attach cassette image and boot it
.TP
\fB-1400
Emulate the Atari 1400XL
.TP
\fB-xld
Emulate the Atari 1450XLD
.TP
\fB-bb
Emulate the CSS Black Box
.TP
\fB-mio
Emulate the ICD MIO board
.TP
\fB-nopatch
Normally the OS is patched giving very fast I/O. This options prevents
the patch from being applied so that the OS accesses the serial port
hardware directly. This option will probably never be needed since
programs that access the serial hardware should work even if the OS
has been patched.
.TP
\fB-nopatchall
Don't patch OS at all, H:, P: and R: devices won't work
.TP
\fB-H1 <path>
Set path for H1: device
.TP
\fB-H2 <path>
Set path for H2: device
.TP
\fB-H3 <path>
Set path for H3: device
.TP
\fB-H4 <path>
Set path for H4: device
.TP
\fB-Hpath <path>
Set path for Atari executables on the H: device
.TP
\fB-hreadonly
Enable read-only mode for H: device
.TP
\fB-hreadwrite
Disable read-only mode for H: device
.TP
\fB-devbug
Put debugging messages for H: and P: devices in log file
.TP
\fB-rtime
Enable R-Time 8 emulation
.TP
\fB-nortime
Disable R-Time 8 emulation
.TP
\fBrdevice [<dev>]
Enable R: device. If <dev> is specified then it's used as host serial device
name (e.g. /dev/ttyS0 on linux). If there is no <dev> specified then R:
is directed to network.
.TP
\fB-mouse off
Do not use mouse
.TP
\fB-mouse pad
Emulate paddles
.TP
\fB-mouse touch
Emulate Atari Touch Tablet
.TP
\fB-mouse koala
Emulate Koala Pad
.TP
\fB-mouse pen
Emulate Light Pen
.TP
\fB-mouse gun
Emulate Light Gun
.TP
\fB-mouse amiga
Emulate Amiga mouse
.TP
\fB-mouse st
Emulate Atari ST mouse
.TP
\fB-mouse trak
Emulate Atari Trak-Ball
.TP
\fB-mouse joy
Emulate joystick using mouse
.TP
\fB-mouseport <num>
Set mouse port 1-4 (default 1)
.TP
\fB-mousespeed <num>
Set mouse speed 1-9 (default 3)
.TP
\fB-multijoy
Emulate MultiJoy4 interface
.TP
\fB-directmouse
Use mouse's absolute position
.TP
\fB-cx85 <num>
Emulate CX85 numeric keypad on port <num>
.TP
\fB-grabmouse
SDL only, prevent mouse pointer from leaving the window
.TP
\fB-record <filename>
Record all input events to <filename>. Can be used for gaming contests
(highest score etc).
.TP
\fB-playback <filename>
Playback input events from <filename>. Watch an expert play the game.
.TP
\fB-refresh
Controls screen refresh rate. A numerical value follows this option
which specifies how many emulated screen updates are required before
the actual screen is updated. This value effects the speed of the
emulation: A higher value results in faster CPU emulation but a
less frequently updated screen.
.TP
\fB-artif <mode>
Set artifacting mode 0-4 (0 = disable)
.TP
\fB-paletten/p <filename>
Read Atari NTSC/PAL colors from ACT file
.TP
\fB-blackn/p <num>
Set NTSC/PAL black level 0-255
.TP
\fB-whiten/p <num>
Set NTSC/PAL white level 0-255
.TP
\fB-colorsn/p <num>
Set NTSC/PAL color intensity
.TP
\fB-genpaln/p
Generate artifical NTSC/PAL palette
.TP
\fB-colshiftn/p <num>
Set color shift (-genpal only)
.TP
\fB-screenshots <pattern>
Set filename pattern for screenshots. Use to override the default
atari000.png, atari001.png etc. filenames. Hashes are replaced with
raising numbers. Existing files are overwritten only if all the files
defined by the pattern exist.
.TP
\fB-showspeed
Show percentage of actual speed
.TP
\fB-sound
Enable sound
.TP
\fB-nosound
Disable sound
.TP
\fB-dsprate <freq>
Set mixing frequency (Hz)
.TP
\fB-snddelay <time>
Set sound delay (milliseconds)
.SS Curses Options
.TP
\fB-left
Use columns 0 to 39
.TP
\fB-central
Use columns 20 to 59
.TP
\fB-right
Use columns 40 to 79
.TP
\fB-wide1
Use columns 0 to 79. In this mode only the even character positions
are used. The odd locations are filled with spaces.
.TP
\fB-wide2
Use columns 0 to 79. This mode is similar to \fB-wide1\fP except that
the spaces are in reverse video if the previous character was also
in reverse video.
.SS Falcon Options
.TP
\fB-interlace <x>
Generate Falcon screen only every x frame
.TP
\fB-videl
Direct VIDEL programming (Falcon/VGA only)
.TP
\fB-double
Double the screen size on NOVA
.TP
\fB-delta
Delta screen output (differences only)
.TP
\fB-joyswap
Swap joysticks
.SS Java NestedVM
.TP
\fB-scale <n>
Scale width and height by <n>
.SS SDL Options
.TP
\fB-fullscreen
Start in fullscreen mode (tries to switch to 336x240 resolution)
.TP
\fB-windowed
Start in a window (does not change your working resolution)
.TP
\fB-rotate90
Run the emulator with rotated display (useful for devices with 240x320
screen)
.TP
\fB-width number-of-pixels
Host horizontal resolution for fullscreen
.TP
\fB-height number-of-pixels
Host vertical resolution for fullscreen
.TP
\fB-bpp number-of-bits
Host color depth for running in fullscreen
.TP
\fB-audio16
Enable 16-bit sound output
.TP
\fB-nojoystick
Do not initialize SDL joysticks
.TP
\fB-joy0 path-to-device
Define path to device used in LPTjoy 0. Available on linux-ia32 only.
.TP
\fB-joy1 path-to-device
Define path to device used in LPTjoy 1. Available on linux-ia32 only.
.TP
\fB-ntscemu
Emulate NTSC composite video (640x480x16 only)
This includes NTSC TV artifacts. "-artif" is not needed in this mode and will
not work. This mode does not use a palette. The video signal is emulated
instead. Palette options such as -genpaln have no effect in this mode.
The following items are for -ntscemu only:
.TP
\fB-ntsc_hue <n>
Set NTSC hue -1..1 (like TV Tint control)
.TP
\fB-ntsc_sat <n>
Set NTSC saturation (like TV Colour control)
.TP
\fB-ntsc_cont <n>
Set NTSC contrast (also called white level)
.TP
\fB-ntsc_bright <n>
Set NTSC brightness (also called black level)
.TP
\fB-ntsc_sharp <n>
Set NTSC sharpness
.TP
\fB-ntsc_burst <n>
Set NTSC burst phase (artificating colours) (CTIA?) Drol, Choplifter,
Ultima: 0.70
.TP
\fB-ntsc_gauss <n>
Set NTSC Gaussian factor (can affect artifacting colours, sharpness and
ghosting)
.TP
\fB-ntsc_gamma <n>
Set NTSC gamma adjustment
.TP
\fB-ntsc_ramp <n>
Set NTSC saturation ramp factor (amount by which bright colours become
desaturated or washed out)
.TP
\fB-scanlines <n>
Set scanlines percentage (ntscemu only)
.TP
\fB-scanlinesnoint
Disable scanlines interpolation (ntscemu only)
.TP
\fB-proto80
Emulate a prototype 80 column board for the 1090
.TP
\fB-xep80
Emulate the XEP80
.TP
\fB-xep80port <n>
Use XEP80 on joystick port <n>
.SS X11 Options
.TP
\fB-small
Run the emulator in a small window where each Atari 800 pixel is
represented by one X Window pixel
.TP
\fB-large
Runs the emulator in a large window where each Atari 800 pixel is
represented by a 2x2 X Window rectange. This mode is selected by
default.
.TP
\fB-huge
Runs the emulator in a huge window where each Atari 800 pixel is
represented by a 3x3 X Window rectange
.TP
\fB-clip_x number-of-pixels
Set left offset for clipping
.TP
\fB-clip_width number-of-pixels
Set the width of the clipping-area
.TP
\fB-clip_y number-of-pixels
Set top offset for clipping
.TP
\fB-clip_height number-of-pixels
Set the height of the clipping-area
.TP
\fB-private_cmap
Use private colormap
.TP
\fB-sio
Show SIO monitor
.TP
\fB-x11bug
Enable debug code in atari_x11.c
.TP
\fB-keypad
Keypad mode
.PD 0
.SH KEYBOARD, JOYSTICK AND OTHER CONTROLLERS
.TP
\fBF1
Built in user interface
.TP
\fBF2
Option key
.TP
\fBF3
Select key
.TP
\fBF4
Start key
.TP
\fBF5
Reset key ("warm reset")
.TP
\fBShift+F5
Reboot ("cold reset")
.TP
\fBF6
Help key (XL/XE only)
.TP
\fBF7
Break key
.TP
\fBF8
Enter monitor
.TP
\fBF9
Exit emulator
.TP
\fBF10
Save screenshot
.TP
\fBShift+F10
Save interlaced screenshot
.TP
\fBAlt+R
Run Atari program
.TP
\fBAlt+D
Disk management
.TP
\fBAlt+C
Cartridge management
.TP
\fBAlt+Y
Select system
.TP
\fBAlt+O
Sound settings
.TP
\fBAlt+W
Sound recording start/stop
.TP
\fBAlt+S
Save state file
.TP
\fBAlt+L
Load state file
.TP
\fBAlt+A
About the emulator
.TP
\fBInsert
Insert line (Atari Shift+'>')
.TP
\fBCtrl+Insert
Insert character (Atari Ctrl+'>')
.TP
\fBShift+Ctrl+Insert
Shift+Ctrl+'>'
.TP
\fBDelete
Delete line (Atari Shift+Backspace)
.TP
\fBShift+Backspace
Delete line (Atari Shift+Backspace)
.TP
\fBCtrl+Delete
Delete character (Atari Ctrl+Backspace)
.TP
\fBCtrl+Backspace
Delete character (Atari Ctrl+Backspace)
.TP
\fBShift+Ctrl+Delete
Shift+Ctrl+Backspace
.TP
\fBShift+Ctrl+Backspace
Shift+Ctrl+Backspace
.TP
\fBHome
Clear (Atari Shift+'<')
.TP
\fBCtrl+Home
Ctrl+'<' (also clears screen)
.TP
\fBShift+Ctrl+Home
Shift+Ctrl+'<'
.TP
\fB~
Inverse video
.TP
\fBUp
Up (Atari Ctrl+'-')
.TP
\fBDown
Down (Atari Ctrl+'=')
.TP
\fBLeft
Left (Atari ctrl+'+')
.TP
\fBRight
Right (Atari ctrl+'*')
.TP
\fBCtrl+Up
-
.TP
\fBCtrl+Down
=
.TP
\fBCtrl+Left
+
.TP
\fBCtrl+Right
*
.TP
\fBShift+Up
_ (Atari Shift+'-')
.TP
\fBShift+Down
| (Atari Shift+'=')
.TP
\fBShift+Left
\ (Atari Shift+'+')
.TP
\fBShift+Right
^ (Atari Shift+'*')
.TP
\fBShift+Ctrl+Up
Shift+Ctrl+-
.TP
\fBShift+Ctrl+Down
Shift+Ctrl+=
.TP
\fBCtrl+'\\'
Ctrl+Esc (Workaround for Windows)
.TP
\fBShift+Ctrl+'\\'
Shift+Ctrl+Esc (Workaround for Windows)
.PP
CX85 Keypad (if enabled):
.TP
\fBhost keypad 0123456789-.
0123456789-.
.TP
\fBhost keypad /
NO
.TP
\fBhost keypad Ctrl+/
ESCAPE
.TP
\fBhost keypad *
DELETE
.TP
\fBhost keypad +
YES
.TP
\fBhost keypad Enter
+ENTER
.PP
Paddles, Atari touch tablet, Koala pad, light pen, light gun,
ST/Amiga mouse, Atari trak-ball, joystick and Atari 5200 analog
controller are emulated using mouse on ports that support it.
See the options above for how to enable mouse.
.SS Basic
No function keys or Alt+letter shortcuts.
Use Ctrl+C to enter the monitor.
Controllers not supported in this version.
.SS Curses
F10 (Save screenshot) does not work in the default CURSES_BASIC build.
Shift+F5 and Shift+F10 don't work at all.
Avoid Ctrl + C, H, J, M, Q, S and Z. The remaining control characters
can be typed. Control characters are displayed on the screen
with the associated upper case character in bold.
Controllers not supported in this version.
.SS Falcon
.TP
\fBHelp
Help key (XL/XE)
.PP
Joystick 0 is operated by the numeric keypad (make sure that the numeric
keypad has been enabled).
7 8 9
\\|/
4 5 6
/|\\
1 2 3
And 0 is the fire key.
Mouse not supported in this version.
.SS SDL
.TP
\fB`
Atari/Inverse key
.TP
\fBLSUPER
Atari/Inverse key (unusable under Windows)
.TP
\fBRSUPER
CapsToggle (+Shift = CapsLock)
.TP
\fBLAlt+F
Switch fullscreen (probably doesn't work in Windows)
.TP
\fBLAlt+G
Switch WIDTH_MODE (so you can set 320x240)
.TP
\fBLAlt+B
Switch BLACK-AND-WHITE
.TP
\fBLAlt+J
Swap \fBkeyboard_emulated\fP joysticks
.TP
\fBLAlt+E
Switch bpp (for debug only, will be removed soon)
.TP
\fBLAlt+M
Grab mouse (prevents mouse pointer from leaving the window)
These keys work with the NTSC composite video emualtion (-ntscemu):
(This interface should be considered experimental and is subject to change)
.TP
\fBLAlt+1
Decrease NTSC sharpness
.TP
\fBLAlt+2
Increase NTSC sharpness
.TP
\fBLAlt+3
Decrease NTSC saturation (like TV Colour control)
.TP
\fBLAlt+4
Increase NTSC saturation
.TP
\fBLAlt+5
Decrease NTSC brightness (also called black level)
.TP
\fBLAlt+6
Increase NTSC brightness
.TP
\fBLAlt+7
Decrease NTSC contrast (also called white level)
.TP
\fBLAlt+8
Increase NTSC contrast
.TP
\fBLAlt+9
Decrease NTSC burst phase (use this to change artifacting colours)
.TP
\fBLAlt+0
Increase NTSC burst phase
.TP
\fBLAlt+-
Decrease NTSC Gaussian factor (ghosting, sharpness, artif colours)
.TP
\fBLAlt+=
Increase NTSC Gaussian factor (ghosting, sharpness, artif colours)
.TP
\fBLAlt+[
Decrease scanlines percentage (NTSC mode only)
.TP
\fBLAlt+]
Increase scanlines percentage (NTSC mode only)
.TP
\fBLAlt+;
Decrease NTSC hue (like TV Tint control)
.TP
\fBLAlt+'
Increase NTSC hue (like TV Tint control)
.TP
\fBLAlt+Ins
Decrease NTSC saturation ramp(reduce saturation for bright colours)
.TP
\fBLAlt+Ins
Increase NTSC saturation ramp(reduce saturation for bright colours)
.TP
\fBLAlt+Shift+X
Enable/disable XEP80 screen (use with -xep80)
.PP
Apart from standard joysticks (handled by the SDL) up to two keyboard joysticks
are supported. The keys used for joystick directions and the trigger can be
freely defined in the config UI (Controller Config -> Define layout).
Keyboard joystick emulation can be enabled/disabled in the Controller Config.
By default, joy 0 is enabled and joy 1 is disabled (to not steal normal
AWDS keys in the emulator).
.SS X11
.TP
\fBAlt
Atari key (either Alt key will work)
.PP
Joystick 0 is operated by the mouse position relative to the center of
the screen. The mouse button acts as the trigger. On Linux, standard
joysticks are also supported.
.PD 1
.SH FILES
.TP
\fI/usr/share/atari800/ATARIOSA.ROM\fR
Atari O/S A
.TP
\fI/usr/share/atari800/ATARIOSB.ROM\fR
Atari O/S B
.TP
\fI/usr/share/atari800/ATARIXL.ROM\fR
Atari 800 XL O/S
.TP
\fI/usr/share/atari800/ATARI5200.ROM\fR
Atari 5200 O/S
.TP
\fI/usr/share/atari800/ATARIBAS.ROM\fR
Atari Basic
.SH BUGS
See the BUGS file.

View File

@@ -0,0 +1,12 @@
Build instructions
unpack atari800-cfg-pelyaSDL.tar.gz into ~/commandergenius/project/jni/application
Download latest atari800 source from http://atari800.cvs.sourceforge.net/atari800
unpack atari800.tar.gz into ~/commandergenius/project/jni/application/atari800
apply patch atari800-2.2.0rc2-cvs.diff
cd ~/commandergenius/project/jni/application
rm src
ln -s atari800 src
cd ~/commandergenius
./build.sh

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -1,216 +0,0 @@
/*
* afile.c - Detection and opening of different Atari file types.
*
* Copyright (c) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "atari.h"
#include "afile.h"
#include "binload.h"
#include "cartridge.h"
#include "cassette.h"
#include "gtia.h"
#include "log.h"
#include "sio.h"
#include "statesav.h"
#include "util.h"
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include <stdio.h>
int AFILE_DetectFileType(const char *filename)
{
UBYTE header[4];
int file_length;
FILE *fp = fopen(filename, "rb");
if (fp == NULL)
return AFILE_ERROR;
if (fread(header, 1, 4, fp) != 4) {
fclose(fp);
return AFILE_ERROR;
}
switch (header[0]) {
case 0:
if (header[1] == 0 && (header[2] != 0 || header[3] != 0) /* && file_length < 37 * 1024 */) {
fclose(fp);
return AFILE_BAS;
}
break;
case 0x1f:
if (header[1] == 0x8b) {
#ifndef HAVE_LIBZ
fclose(fp);
Log_print("\"%s\" is a compressed file.", filename);
Log_print("This executable does not support compressed files. You can uncompress this file");
Log_print("with an external program that supports gzip (*.gz) files (e.g. gunzip)");
Log_print("and then load into this emulator.");
return AFILE_ERROR;
#else /* HAVE_LIBZ */
gzFile gzf;
fclose(fp);
gzf = gzopen(filename, "rb");
if (gzf == NULL)
return AFILE_ERROR;
if (gzread(gzf, header, 4) != 4) {
gzclose(gzf);
return AFILE_ERROR;
}
gzclose(gzf);
if (header[0] == 0x96 && header[1] == 0x02)
return AFILE_ATR_GZ;
if (header[0] == 'A' && header[1] == 'T' && header[2] == 'A' && header[3] == 'R')
return AFILE_STATE_GZ;
return AFILE_XFD_GZ;
#endif /* HAVE_LIBZ */
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if ((header[1] >= '0' && header[1] <= '9') || header[1] == ' ') {
fclose(fp);
return AFILE_LST;
}
break;
case 'A':
if (header[1] == 'T' && header[2] == 'A' && header[3] == 'R') {
fclose(fp);
return AFILE_STATE;
}
break;
case 'C':
if (header[1] == 'A' && header[2] == 'R' && header[3] == 'T') {
fclose(fp);
return AFILE_CART;
}
break;
case 'F':
if (header[1] == 'U' && header[2] == 'J' && header[3] == 'I') {
fclose(fp);
return AFILE_CAS;
}
break;
case 0x96:
if (header[1] == 0x02) {
fclose(fp);
return AFILE_ATR;
}
break;
case 0xf9:
case 0xfa:
fclose(fp);
return AFILE_DCM;
case 0xff:
if (header[1] == 0xff && (header[2] != 0xff || header[3] != 0xff)) {
fclose(fp);
return AFILE_XEX;
}
break;
default:
break;
}
file_length = Util_flen(fp);
fclose(fp);
/* Detect .pro images */
/* # of sectors is in header */
if ((file_length-16)%(128+12) == 0 &&
header[0]*256 + header[1] == (file_length-16)/(128+12) &&
header[2] == 'P') {
#ifdef DEBUG_PRO
Log_print(".pro file detected");
#endif
return AFILE_PRO;
}
/* 40K or a-power-of-two between 4K and CARTRIDGE_MAX_SIZE */
if (file_length >= 4 * 1024 && file_length <= CARTRIDGE_MAX_SIZE
&& ((file_length & (file_length - 1)) == 0 || file_length == 40 * 1024))
return AFILE_ROM;
/* BOOT_TAPE is a raw file containing a program booted from a tape */
if ((header[1] << 7) == file_length)
return AFILE_BOOT_TAPE;
if ((file_length & 0x7f) == 0)
return AFILE_XFD;
return AFILE_ERROR;
}
int AFILE_OpenFile(const char *filename, int reboot, int diskno, int readonly)
{
int type = AFILE_DetectFileType(filename);
switch (type) {
case AFILE_ATR:
case AFILE_XFD:
case AFILE_ATR_GZ:
case AFILE_XFD_GZ:
case AFILE_DCM:
case AFILE_PRO:
if (!SIO_Mount(diskno, filename, readonly))
return AFILE_ERROR;
if (reboot)
Atari800_Coldstart();
break;
case AFILE_XEX:
case AFILE_BAS:
case AFILE_LST:
if (!BINLOAD_Loader(filename))
return AFILE_ERROR;
break;
case AFILE_CART:
case AFILE_ROM:
/* TODO: select format for ROMs; switch 5200 ? */
if (CARTRIDGE_Insert(filename) != 0)
return AFILE_ERROR;
if (reboot)
Atari800_Coldstart();
break;
case AFILE_CAS:
case AFILE_BOOT_TAPE:
if (!CASSETTE_Insert(filename))
return AFILE_ERROR;
if (reboot) {
CASSETTE_hold_start = TRUE;
Atari800_Coldstart();
}
break;
case AFILE_STATE:
case AFILE_STATE_GZ:
#ifdef BASIC
Log_print("State files are not supported in BASIC version");
return AFILE_ERROR;
#else
if (!StateSav_ReadAtariState(filename, "rb"))
return AFILE_ERROR;
/* Don't press Option */
GTIA_consol_table[1] = GTIA_consol_table[2] = 0xf;
break;
#endif
default:
break;
}
return type;
}

View File

@@ -1,49 +0,0 @@
#ifndef AFILE_H_
#define AFILE_H_
/* File types returned by AFILE_DetectFileType() and AFILE_OpenFile(). */
#define AFILE_ERROR 0
#define AFILE_ATR 1
#define AFILE_XFD 2
#define AFILE_ATR_GZ 3
#define AFILE_XFD_GZ 4
#define AFILE_DCM 5
#define AFILE_XEX 6
#define AFILE_BAS 7
#define AFILE_LST 8
#define AFILE_CART 9
#define AFILE_ROM 10
#define AFILE_CAS 11
#define AFILE_BOOT_TAPE 12
#define AFILE_STATE 13
#define AFILE_STATE_GZ 14
#define AFILE_PRO 15
/* ATR format header */
struct AFILE_ATR_Header {
unsigned char magic1;
unsigned char magic2;
unsigned char seccountlo;
unsigned char seccounthi;
unsigned char secsizelo;
unsigned char secsizehi;
unsigned char hiseccountlo;
unsigned char hiseccounthi;
unsigned char gash[7];
unsigned char writeprotect;
};
/* First two bytes of an ATR file. */
#define AFILE_ATR_MAGIC1 0x96
#define AFILE_ATR_MAGIC2 0x02
/* Auto-detects file type and returns one of AFILE_* values. */
int AFILE_DetectFileType(const char *filename);
/* Auto-detects file type and mounts the file in the emulator.
reboot: Atari800_Coldstart() for disks, cartridges and tapes
diskno: drive number for disks (1-8)
readonly: mount disks as read-only */
int AFILE_OpenFile(const char *filename, int reboot, int diskno, int readonly);
#endif /* AFILE_H_ */

View File

@@ -1,246 +0,0 @@
#ifndef AKEY_H_
#define AKEY_H_
/* akey.h: Atari key codes */
/* INPUT_key_code values */
#define AKEY_NONE -1
/* Special key codes. */
#define AKEY_WARMSTART -2
#define AKEY_COLDSTART -3
#define AKEY_EXIT -4
#define AKEY_BREAK -5
#define AKEY_UI -7
#define AKEY_SCREENSHOT -8
#define AKEY_SCREENSHOT_INTERLACE -9
#define AKEY_START -10
#define AKEY_SELECT -11
#define AKEY_OPTION -12
#define AKEY_PBI_BB_MENU -13
#define AKEY_CX85_1 -14
#define AKEY_CX85_2 -15
#define AKEY_CX85_3 -16
#define AKEY_CX85_4 -17
#define AKEY_CX85_5 -18
#define AKEY_CX85_6 -19
#define AKEY_CX85_7 -20
#define AKEY_CX85_8 -21
#define AKEY_CX85_9 -22
#define AKEY_CX85_0 -23
#define AKEY_CX85_PERIOD -24
#define AKEY_CX85_MINUS -25
#define AKEY_CX85_PLUS_ENTER -26
#define AKEY_CX85_ESCAPE -27
#define AKEY_CX85_NO -28
#define AKEY_CX85_DELETE -29
#define AKEY_CX85_YES -30
#define AKEY_SHFT 0x40
#define AKEY_CTRL 0x80
#define AKEY_SHFTCTRL 0xc0
#define AKEY_0 0x32
#define AKEY_1 0x1f
#define AKEY_2 0x1e
#define AKEY_3 0x1a
#define AKEY_4 0x18
#define AKEY_5 0x1d
#define AKEY_6 0x1b
#define AKEY_7 0x33
#define AKEY_8 0x35
#define AKEY_9 0x30
#define AKEY_CTRL_0 (AKEY_CTRL | AKEY_0)
#define AKEY_CTRL_1 (AKEY_CTRL | AKEY_1)
#define AKEY_CTRL_2 (AKEY_CTRL | AKEY_2)
#define AKEY_CTRL_3 (AKEY_CTRL | AKEY_3)
#define AKEY_CTRL_4 (AKEY_CTRL | AKEY_4)
#define AKEY_CTRL_5 (AKEY_CTRL | AKEY_5)
#define AKEY_CTRL_6 (AKEY_CTRL | AKEY_6)
#define AKEY_CTRL_7 (AKEY_CTRL | AKEY_7)
#define AKEY_CTRL_8 (AKEY_CTRL | AKEY_8)
#define AKEY_CTRL_9 (AKEY_CTRL | AKEY_9)
#define AKEY_a 0x3f
#define AKEY_b 0x15
#define AKEY_c 0x12
#define AKEY_d 0x3a
#define AKEY_e 0x2a
#define AKEY_f 0x38
#define AKEY_g 0x3d
#define AKEY_h 0x39
#define AKEY_i 0x0d
#define AKEY_j 0x01
#define AKEY_k 0x05
#define AKEY_l 0x00
#define AKEY_m 0x25
#define AKEY_n 0x23
#define AKEY_o 0x08
#define AKEY_p 0x0a
#define AKEY_q 0x2f
#define AKEY_r 0x28
#define AKEY_s 0x3e
#define AKEY_t 0x2d
#define AKEY_u 0x0b
#define AKEY_v 0x10
#define AKEY_w 0x2e
#define AKEY_x 0x16
#define AKEY_y 0x2b
#define AKEY_z 0x17
#define AKEY_A (AKEY_SHFT | AKEY_a)
#define AKEY_B (AKEY_SHFT | AKEY_b)
#define AKEY_C (AKEY_SHFT | AKEY_c)
#define AKEY_D (AKEY_SHFT | AKEY_d)
#define AKEY_E (AKEY_SHFT | AKEY_e)
#define AKEY_F (AKEY_SHFT | AKEY_f)
#define AKEY_G (AKEY_SHFT | AKEY_g)
#define AKEY_H (AKEY_SHFT | AKEY_h)
#define AKEY_I (AKEY_SHFT | AKEY_i)
#define AKEY_J (AKEY_SHFT | AKEY_j)
#define AKEY_K (AKEY_SHFT | AKEY_k)
#define AKEY_L (AKEY_SHFT | AKEY_l)
#define AKEY_M (AKEY_SHFT | AKEY_m)
#define AKEY_N (AKEY_SHFT | AKEY_n)
#define AKEY_O (AKEY_SHFT | AKEY_o)
#define AKEY_P (AKEY_SHFT | AKEY_p)
#define AKEY_Q (AKEY_SHFT | AKEY_q)
#define AKEY_R (AKEY_SHFT | AKEY_r)
#define AKEY_S (AKEY_SHFT | AKEY_s)
#define AKEY_T (AKEY_SHFT | AKEY_t)
#define AKEY_U (AKEY_SHFT | AKEY_u)
#define AKEY_V (AKEY_SHFT | AKEY_v)
#define AKEY_W (AKEY_SHFT | AKEY_w)
#define AKEY_X (AKEY_SHFT | AKEY_x)
#define AKEY_Y (AKEY_SHFT | AKEY_y)
#define AKEY_Z (AKEY_SHFT | AKEY_z)
#define AKEY_CTRL_a (AKEY_CTRL | AKEY_a)
#define AKEY_CTRL_b (AKEY_CTRL | AKEY_b)
#define AKEY_CTRL_c (AKEY_CTRL | AKEY_c)
#define AKEY_CTRL_d (AKEY_CTRL | AKEY_d)
#define AKEY_CTRL_e (AKEY_CTRL | AKEY_e)
#define AKEY_CTRL_f (AKEY_CTRL | AKEY_f)
#define AKEY_CTRL_g (AKEY_CTRL | AKEY_g)
#define AKEY_CTRL_h (AKEY_CTRL | AKEY_h)
#define AKEY_CTRL_i (AKEY_CTRL | AKEY_i)
#define AKEY_CTRL_j (AKEY_CTRL | AKEY_j)
#define AKEY_CTRL_k (AKEY_CTRL | AKEY_k)
#define AKEY_CTRL_l (AKEY_CTRL | AKEY_l)
#define AKEY_CTRL_m (AKEY_CTRL | AKEY_m)
#define AKEY_CTRL_n (AKEY_CTRL | AKEY_n)
#define AKEY_CTRL_o (AKEY_CTRL | AKEY_o)
#define AKEY_CTRL_p (AKEY_CTRL | AKEY_p)
#define AKEY_CTRL_q (AKEY_CTRL | AKEY_q)
#define AKEY_CTRL_r (AKEY_CTRL | AKEY_r)
#define AKEY_CTRL_s (AKEY_CTRL | AKEY_s)
#define AKEY_CTRL_t (AKEY_CTRL | AKEY_t)
#define AKEY_CTRL_u (AKEY_CTRL | AKEY_u)
#define AKEY_CTRL_v (AKEY_CTRL | AKEY_v)
#define AKEY_CTRL_w (AKEY_CTRL | AKEY_w)
#define AKEY_CTRL_x (AKEY_CTRL | AKEY_x)
#define AKEY_CTRL_y (AKEY_CTRL | AKEY_y)
#define AKEY_CTRL_z (AKEY_CTRL | AKEY_z)
#define AKEY_CTRL_A (AKEY_CTRL | AKEY_A)
#define AKEY_CTRL_B (AKEY_CTRL | AKEY_B)
#define AKEY_CTRL_C (AKEY_CTRL | AKEY_C)
#define AKEY_CTRL_D (AKEY_CTRL | AKEY_D)
#define AKEY_CTRL_E (AKEY_CTRL | AKEY_E)
#define AKEY_CTRL_F (AKEY_CTRL | AKEY_F)
#define AKEY_CTRL_G (AKEY_CTRL | AKEY_G)
#define AKEY_CTRL_H (AKEY_CTRL | AKEY_H)
#define AKEY_CTRL_I (AKEY_CTRL | AKEY_I)
#define AKEY_CTRL_J (AKEY_CTRL | AKEY_J)
#define AKEY_CTRL_K (AKEY_CTRL | AKEY_K)
#define AKEY_CTRL_L (AKEY_CTRL | AKEY_L)
#define AKEY_CTRL_M (AKEY_CTRL | AKEY_M)
#define AKEY_CTRL_N (AKEY_CTRL | AKEY_N)
#define AKEY_CTRL_O (AKEY_CTRL | AKEY_O)
#define AKEY_CTRL_P (AKEY_CTRL | AKEY_P)
#define AKEY_CTRL_Q (AKEY_CTRL | AKEY_Q)
#define AKEY_CTRL_R (AKEY_CTRL | AKEY_R)
#define AKEY_CTRL_S (AKEY_CTRL | AKEY_S)
#define AKEY_CTRL_T (AKEY_CTRL | AKEY_T)
#define AKEY_CTRL_U (AKEY_CTRL | AKEY_U)
#define AKEY_CTRL_V (AKEY_CTRL | AKEY_V)
#define AKEY_CTRL_W (AKEY_CTRL | AKEY_W)
#define AKEY_CTRL_X (AKEY_CTRL | AKEY_X)
#define AKEY_CTRL_Y (AKEY_CTRL | AKEY_Y)
#define AKEY_CTRL_Z (AKEY_CTRL | AKEY_Z)
#define AKEY_HELP 0x11
#define AKEY_DOWN 0x8f
#define AKEY_LEFT 0x86
#define AKEY_RIGHT 0x87
#define AKEY_UP 0x8e
#define AKEY_BACKSPACE 0x34
#define AKEY_DELETE_CHAR 0xb4
#define AKEY_DELETE_LINE 0x74
#define AKEY_INSERT_CHAR 0xb7
#define AKEY_INSERT_LINE 0x77
#define AKEY_ESCAPE 0x1c
#define AKEY_ATARI 0x27
#define AKEY_CAPSLOCK 0x7c
#define AKEY_CAPSTOGGLE 0x3c
#define AKEY_TAB 0x2c
#define AKEY_SETTAB 0x6c
#define AKEY_CLRTAB 0xac
#define AKEY_RETURN 0x0c
#define AKEY_SPACE 0x21
#define AKEY_EXCLAMATION 0x5f
#define AKEY_DBLQUOTE 0x5e
#define AKEY_HASH 0x5a
#define AKEY_DOLLAR 0x58
#define AKEY_PERCENT 0x5d
#define AKEY_AMPERSAND 0x5b
#define AKEY_QUOTE 0x73
#define AKEY_AT 0x75
#define AKEY_PARENLEFT 0x70
#define AKEY_PARENRIGHT 0x72
#define AKEY_LESS 0x36
#define AKEY_GREATER 0x37
#define AKEY_EQUAL 0x0f
#define AKEY_QUESTION 0x66
#define AKEY_MINUS 0x0e
#define AKEY_PLUS 0x06
#define AKEY_ASTERISK 0x07
#define AKEY_SLASH 0x26
#define AKEY_COLON 0x42
#define AKEY_SEMICOLON 0x02
#define AKEY_COMMA 0x20
#define AKEY_FULLSTOP 0x22
#define AKEY_UNDERSCORE 0x4e
#define AKEY_BRACKETLEFT 0x60
#define AKEY_BRACKETRIGHT 0x62
#define AKEY_CIRCUMFLEX 0x47
#define AKEY_BACKSLASH 0x46
#define AKEY_BAR 0x4f
#define AKEY_CLEAR (AKEY_SHFT | AKEY_LESS)
#define AKEY_CARET (AKEY_SHFT | AKEY_ASTERISK)
#define AKEY_F1 0x03
#define AKEY_F2 0x04
#define AKEY_F3 0x13
#define AKEY_F4 0x14
/* Following keys cannot be read with both shift and control pressed:
J K L ; + * Z X C V B F1 F2 F3 F4 HELP */
/* 5200 key codes */
#define AKEY_5200_START 0x39
#define AKEY_5200_PAUSE 0x31
#define AKEY_5200_RESET 0x29
#define AKEY_5200_0 0x25
#define AKEY_5200_1 0x3f
#define AKEY_5200_2 0x3d
#define AKEY_5200_3 0x3b
#define AKEY_5200_4 0x37
#define AKEY_5200_5 0x35
#define AKEY_5200_6 0x33
#define AKEY_5200_7 0x2f
#define AKEY_5200_8 0x2d
#define AKEY_5200_9 0x2b
#define AKEY_5200_HASH 0x23
#define AKEY_5200_ASTERISK 0x27
#endif /* AKEY_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,137 +0,0 @@
#ifndef ANTIC_H_
#define ANTIC_H_
#include "atari.h"
/*
* Offset to registers in custom relative to start of antic memory addresses.
*/
#define ANTIC_OFFSET_DMACTL 0x00
#define ANTIC_OFFSET_CHACTL 0x01
#define ANTIC_OFFSET_DLISTL 0x02
#define ANTIC_OFFSET_DLISTH 0x03
#define ANTIC_OFFSET_HSCROL 0x04
#define ANTIC_OFFSET_VSCROL 0x05
#define ANTIC_OFFSET_PMBASE 0x07
#define ANTIC_OFFSET_CHBASE 0x09
#define ANTIC_OFFSET_WSYNC 0x0a
#define ANTIC_OFFSET_VCOUNT 0x0b
#define ANTIC_OFFSET_PENH 0x0c
#define ANTIC_OFFSET_PENV 0x0d
#define ANTIC_OFFSET_NMIEN 0x0e
#define ANTIC_OFFSET_NMIRES 0x0f
#define ANTIC_OFFSET_NMIST 0x0f
extern UBYTE ANTIC_CHACTL;
extern UBYTE ANTIC_CHBASE;
extern UWORD ANTIC_dlist;
extern UBYTE ANTIC_DMACTL;
extern UBYTE ANTIC_HSCROL;
extern UBYTE ANTIC_NMIEN;
extern UBYTE ANTIC_NMIST;
extern UBYTE ANTIC_PMBASE;
extern UBYTE ANTIC_VSCROL;
extern int ANTIC_break_ypos;
extern int ANTIC_ypos;
extern int ANTIC_wsync_halt;
/* Current clock cycle in a scanline.
Normally 0 <= ANTIC_xpos && ANTIC_xpos < ANTIC_LINE_C, but in some cases ANTIC_xpos >= ANTIC_LINE_C,
which means that we are already in line (ypos + 1). */
extern int ANTIC_xpos;
/* ANTIC_xpos limit for the currently running 6502 emulation. */
extern int ANTIC_xpos_limit;
/* Main clock value at the beginning of the current scanline. */
extern unsigned int ANTIC_screenline_cpu_clock;
/* Current main clock value. */
#define ANTIC_CPU_CLOCK (ANTIC_screenline_cpu_clock + ANTIC_xpos)
#define ANTIC_NMIST_C 6
#define ANTIC_NMI_C 12
/* Number of cycles per scanline. */
#define ANTIC_LINE_C 114
/* STA WSYNC resumes here. */
#define ANTIC_WSYNC_C 106
/* Number of memory refresh cycles per scanline.
In the first scanline of a font mode there are actually less than ANTIC_DMAR
memory refresh cycles. */
#define ANTIC_DMAR 9
extern int ANTIC_artif_mode;
extern int ANTIC_artif_new;
extern UBYTE ANTIC_PENH_input;
extern UBYTE ANTIC_PENV_input;
int ANTIC_Initialise(int *argc, char *argv[]);
void ANTIC_Reset(void);
void ANTIC_Frame(int draw_display);
UBYTE ANTIC_GetByte(UWORD addr);
void ANTIC_PutByte(UWORD addr, UBYTE byte);
UBYTE ANTIC_GetDLByte(UWORD *paddr);
UWORD ANTIC_GetDLWord(UWORD *paddr);
/* always call ANTIC_UpdateArtifacting after changing ANTIC_artif_mode */
void ANTIC_UpdateArtifacting(void);
/* Video memory access */
void ANTIC_VideoMemset(UBYTE *ptr, UBYTE val, ULONG size);
void ANTIC_VideoPutByte(UBYTE *ptr, UBYTE val);
/* GTIA calls it on a write to PRIOR */
void ANTIC_SetPrior(UBYTE prior);
/* Saved states */
void ANTIC_StateSave(void);
void ANTIC_StateRead(void);
/* Pointer to 16 KB seen by ANTIC in 0x4000-0x7fff.
If it's the same what the CPU sees (and what's in memory[0x4000..0x7fff],
then NULL. */
extern const UBYTE *ANTIC_xe_ptr;
/* PM graphics for GTIA */
extern int ANTIC_player_dma_enabled;
extern int ANTIC_missile_dma_enabled;
extern int ANTIC_player_gra_enabled;
extern int ANTIC_missile_gra_enabled;
extern int ANTIC_player_flickering;
extern int ANTIC_missile_flickering;
/* ANTIC colour lookup tables, used by GTIA */
extern UWORD ANTIC_cl[128];
extern ULONG ANTIC_lookup_gtia9[16];
extern ULONG ANTIC_lookup_gtia11[16];
extern UWORD ANTIC_hires_lookup_l[128];
#ifdef NEW_CYCLE_EXACT
#define ANTIC_NOT_DRAWING -999
#define ANTIC_DRAWING_SCREEN (ANTIC_cur_screen_pos!=ANTIC_NOT_DRAWING)
extern int ANTIC_delayed_wsync;
extern int ANTIC_cur_screen_pos;
extern const int *ANTIC_cpu2antic_ptr;
extern const int *ANTIC_antic2cpu_ptr;
void ANTIC_UpdateScanline(void);
void ANTIC_UpdateScanlinePrior(UBYTE byte);
#ifndef NO_GTIA11_DELAY
extern int ANTIC_prior_curpos;
#define ANTIC_PRIOR_BUF_SIZE 40
extern UBYTE ANTIC_prior_val_buf[ANTIC_PRIOR_BUF_SIZE];
extern int ANTIC_prior_pos_buf[ANTIC_PRIOR_BUF_SIZE];
#endif /* NO_GTIA11_DELAY */
#define ANTIC_XPOS ( ANTIC_DRAWING_SCREEN ? ANTIC_cpu2antic_ptr[ANTIC_xpos] : ANTIC_xpos )
#else
#define ANTIC_XPOS ANTIC_xpos
#endif /* NEW_CYCLE_EXACT */
#endif /* ANTIC_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +0,0 @@
#ifndef ATARI_H_
#define ATARI_H_
#include "config.h"
#include <stdio.h> /* FILENAME_MAX */
#ifdef WIN32
#include <windows.h>
#endif
/* Fundamental declarations ---------------------------------------------- */
#define Atari800_TITLE "Atari 800 Emulator, Version 2.1.0"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/* SBYTE and UBYTE must be exactly 1 byte long. */
/* SWORD and UWORD must be exactly 2 bytes long. */
/* SLONG and ULONG must be exactly 4 bytes long. */
#define SBYTE signed char
#define SWORD signed short
#define SLONG signed int
#define UBYTE unsigned char
#define UWORD unsigned short
#ifndef WIN32
/* Windows headers typedef ULONG */
#define ULONG unsigned int
#endif
/* Note: in various parts of the emulator we assume that char is 1 byte
and int is 4 bytes. */
/* Public interface ------------------------------------------------------ */
/* Machine type. */
#define Atari800_MACHINE_OSA 0
#define Atari800_MACHINE_OSB 1
#define Atari800_MACHINE_XLXE 2
#define Atari800_MACHINE_5200 3
extern int Atari800_machine_type;
/* Always call Atari800_InitialiseMachine() after changing Atari800_machine_type
or MEMORY_ram_size! */
/* Video system. */
#define Atari800_TV_UNSET 0
#define Atari800_TV_PAL 312
#define Atari800_TV_NTSC 262
/* Video system / Number of scanlines per frame. */
extern int Atari800_tv_mode;
/* TRUE to disable Atari BASIC when booting Atari (hold Option in XL/XE). */
extern int Atari800_disable_basic;
/* If Atari800_Frame() sets it to TRUE, then the current contents
of Screen_atari should be displayed. */
extern int Atari800_display_screen;
/* Simply incremented by Atari800_Frame(). */
extern int Atari800_nframes;
/* How often the screen is updated (1 = every Atari frame). */
extern int Atari800_refresh_rate;
/* Set to TRUE for faster emulation with Atari800_refresh_rate > 1.
Set to FALSE for accurate emulation with Atari800_refresh_rate > 1. */
extern int Atari800_collisions_in_skipped_frames;
/* Initializes Atari800 emulation core. */
int Atari800_Initialise(int *argc, char *argv[]);
/* Emulates one frame (1/50sec for PAL, 1/60sec for NTSC). */
void Atari800_Frame(void);
/* Reboots the emulated Atari. */
void Atari800_Coldstart(void);
/* Presses the Reset key in the emulated Atari. */
void Atari800_Warmstart(void);
/* Reinitializes after Atari800_machine_type or ram_size change.
You should call Atari800_Coldstart() after it. */
int Atari800_InitialiseMachine(void);
/* Shuts down Atari800 emulation core. */
int Atari800_Exit(int run_monitor);
/* Private interface ----------------------------------------------------- */
/* Don't use outside the emulation core! */
/* STAT_UNALIGNED_WORDS is solely for benchmarking purposes.
8-element arrays (stat_arr) represent number of accesses with the given
value of 3 least significant bits of address. This gives us information
about the ratio of aligned vs unaligned accesses. */
#ifdef STAT_UNALIGNED_WORDS
#define UNALIGNED_STAT_DEF(stat_arr) unsigned int stat_arr[8];
#define UNALIGNED_STAT_DECL(stat_arr) extern unsigned int stat_arr[8];
#define UNALIGNED_GET_WORD(ptr, stat_arr) (stat_arr[(unsigned int) (ptr) & 7]++, *(const UWORD *) (ptr))
#define UNALIGNED_PUT_WORD(ptr, value, stat_arr) (stat_arr[(unsigned int) (ptr) & 7]++, *(UWORD *) (ptr) = (value))
#define UNALIGNED_GET_LONG(ptr, stat_arr) (stat_arr[(unsigned int) (ptr) & 7]++, *(const ULONG *) (ptr))
#define UNALIGNED_PUT_LONG(ptr, value, stat_arr) (stat_arr[(unsigned int) (ptr) & 7]++, *(ULONG *) (ptr) = (value))
UNALIGNED_STAT_DECL(Screen_atari_write_long_stat)
UNALIGNED_STAT_DECL(pm_scanline_read_long_stat)
UNALIGNED_STAT_DECL(memory_read_word_stat)
UNALIGNED_STAT_DECL(memory_write_word_stat)
UNALIGNED_STAT_DECL(memory_read_aligned_word_stat)
UNALIGNED_STAT_DECL(memory_write_aligned_word_stat)
#else
#define UNALIGNED_STAT_DEF(stat_arr)
#define UNALIGNED_STAT_DECL(stat_arr)
#define UNALIGNED_GET_WORD(ptr, stat_arr) (*(const UWORD *) (ptr))
#define UNALIGNED_PUT_WORD(ptr, value, stat_arr) (*(UWORD *) (ptr) = (value))
#define UNALIGNED_GET_LONG(ptr, stat_arr) (*(const ULONG *) (ptr))
#define UNALIGNED_PUT_LONG(ptr, value, stat_arr) (*(ULONG *) (ptr) = (value))
#endif
/* Sleeps until it's time to emulate next Atari frame. */
void Atari800_Sync(void);
/* Load a ROM image filename of size nbytes into buffer */
int Atari800_LoadImage(const char *filename, UBYTE *buffer, int nbytes);
/* Save State */
void Atari800_StateSave(void);
/* Read State */
void Atari800_StateRead(void);
#endif /* ATARI_H_ */

View File

@@ -1,487 +0,0 @@
/* http://www.slack.net/~ant/ */
/* compilable in C or C++; just change the file extension */
#include "atari_ntsc.h"
#include "log.h"
#include <string.h>
#include <math.h>
#include <stdlib.h>
/* Based on algorithm by NewRisingSun */
/* License note by Perry: Expat License.
* http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses
* "This is a simple, permissive non-copyleft free software license, compatible with the GNU GPL."*/
/* Copyright (C) 2006 Shay Green. Permission is hereby granted, free of
charge, to any person obtaining a copy of this software module and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the
following conditions: The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software. THE
SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
enum { composite_border = 6 };
enum { center_offset = 1 };
enum { alignment_count = 4 }; /* different pixel alignments with respect to yiq quads */
enum { rgb_kernel_size = atari_ntsc_entry_size / alignment_count };
/* important to use + and not | since values are signed */
#define MAKE_KRGB( r, g, b ) \
( ((r + 16) >> 5 << 20) + ((g + 16) >> 5 << 10) + ((b + 16) >> 5) )
static float const rgb_unit = 0x1000;
#define MAKE_KMASK( x ) (((x) << 20) | ((x) << 10) | (x))
/* clamp each RGB component to 0 to 0x7F range (low two bits are trashed) */
#define CLAMP_RGB( io, adj ) {\
ntsc_rgb_t sub = (io) >> (7 + adj) & MAKE_KMASK( 3 );\
ntsc_rgb_t clamp = MAKE_KMASK( 0x202 ) - sub;\
io = ((io) | clamp) & (clamp - sub);\
}
enum { composite_size = composite_border + 8 + composite_border };
enum { rgb_pad = (center_offset + composite_border + 7) / 8 * 8 - center_offset - composite_border };
enum { rgb_size = (rgb_pad + composite_size + 7) / 8 * 8 };
enum { rescaled_size = rgb_size / 8 * 7 };
enum { ntsc_kernel_size = composite_size * 2 };
typedef struct ntsc_to_rgb_t
{
float composite [composite_size];
float to_rgb [6];
float brightness;
float contrast;
float sharpness;
short rgb [rgb_size] [3];
short rescaled [rescaled_size + 1] [3]; /* extra space for sharpen */
float kernel [ntsc_kernel_size];
} ntsc_to_rgb_t;
static float const pi = 3.14159265358979323846f;
static void rotate_matrix( float const* in, float s, float c, float* out )
{
int n = 3;
while ( n-- )
{
float i = *in++;
float q = *in++;
*out++ = i * c - q * s;
*out++ = i * s + q * c;
}
}
static void ntsc_to_rgb_init( ntsc_to_rgb_t* ntsc, atari_ntsc_setup_t const* setup, float hue )
{
static float const to_rgb [6] = { 0.956, 0.621, -0.272, -0.647, -1.105, 1.702 };
float gaussian_factor = 1+setup->gaussian_factor; /* 1 = normal, > 1 reduces echoes of bright objects (was 2.1)*/
float const brightness_bias = rgb_unit / 128; /* reduces vert bands on artifact colored areas */
int i;
/* ranges need to be scaled a bit to avoid pixels overflowing at extremes */
ntsc->brightness = (setup->brightness-0.0f) * (0.4f * rgb_unit) + brightness_bias;
ntsc->contrast = (setup->contrast-0.0f) * 0.4f + 1;
ntsc->sharpness = 1 + (setup->sharpness < 0 ? setup->sharpness * 0.5f : setup->sharpness);
for ( i = 0; i < composite_size; i++ )
ntsc->composite [i] = 0;
/* Generate gaussian kernel, padded with zero */
for ( i = 0; i < ntsc_kernel_size; i++ )
ntsc->kernel [i] = 0;
for ( i = -composite_border; i <= composite_border; i++ )
ntsc->kernel [ntsc_kernel_size / 2 + i] = exp( i * i * (-0.03125f * gaussian_factor) );
/* normalize kernel totals of every fourth sample (at all four phases) to 0.5, otherwise */
/* i/q low-pass will favor one of the four alignments and cause repeating spots */
for ( i = 0; i < 4; i++ )
{
double sum = 0;
float scale;
int x;
for ( x = i; x < ntsc_kernel_size; x += 4 )
sum += ntsc->kernel [x];
scale = 0.5 / sum;
for ( x = i; x < ntsc_kernel_size; x += 4 )
ntsc->kernel [x] *= scale;
}
/* adjust decoder matrix */
{
float sat = setup->saturation + 1;
rotate_matrix( to_rgb, sin( hue ) * sat, cos( hue ) * sat, ntsc->to_rgb );
}
memset( ntsc->rgb, 0, sizeof ntsc->rgb );
}
/* Convert NTSC composite signal to RGB, where composite signal contains only four
non-zero samples beginning at offset */
static void ntsc_to_rgb( ntsc_to_rgb_t const* ntsc, int offset, short* out )
{
float const* kernel = &ntsc->kernel [ntsc_kernel_size / 2 - offset];
float f0 = ntsc->composite [offset];
float f1 = ntsc->composite [offset + 1];
float f2 = ntsc->composite [offset + 2];
float f3 = ntsc->composite [offset + 3];
int x = 0;
while ( x < composite_size )
{
#define PIXEL( get_y ) \
{\
float i = kernel [ 0] * f0 + kernel [-2] * f2;\
float q = kernel [-1] * f1 + kernel [-3] * f3;\
float y = get_y;\
float r = y + i * ntsc->to_rgb [0] + q * ntsc->to_rgb [1];\
float g = y + i * ntsc->to_rgb [2] + q * ntsc->to_rgb [3];\
float b = y + i * ntsc->to_rgb [4] + q * ntsc->to_rgb [5];\
kernel++;\
out [0] = (int) r;\
out [1] = (int) g;\
out [2] = (int) b;\
out += 3;\
}
PIXEL( i - ntsc->composite [x + 0] )
PIXEL( q - ntsc->composite [x + 1] )
PIXEL( ntsc->composite [x + 2] - i )
PIXEL( ntsc->composite [x + 3] - q )
x += 4;
#undef PIXEL
}
}
/* Rescale pixels to NTSC aspect ratio using linear interpolation,
with 7 output pixels for every 8 input pixels, linear interpolation */
static void rescale( short const* in, int count, short* out )
{
do
{
int const accuracy = 16;
int const unit = 1 << accuracy;
int const step = unit / 8;
int left = unit - step;
int right = step;
int n = 7;
while ( n-- )
{
int r = (in [0] * left + in [3] * right) >> accuracy;
int g = (in [1] * left + in [4] * right) >> accuracy;
int b = (in [2] * left + in [5] * right) >> accuracy;
*out++ = r;
*out++ = g;
*out++ = b;
left -= step;
right += step;
in += 3;
}
in += 3;
}
while ( (count -= 7) > 0 );
}
/* sharpen image using (level-1)/2, level, (level-1)/2 convolution kernel */
static void sharpen( short const* in, float level, int count, short* out )
{
/* to do: sharpen luma only? */
int const accuracy = 16;
int const middle = (int) (level * (1 << accuracy));
int const side = (middle - (1 << accuracy)) >> 1;
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
for ( count = (count - 2) * 3; count--; in++ )
*out++ = (in [0] * middle - in [-3] * side - in [3] * side) >> accuracy;
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
}
/* Generate pixel and capture into table */
static ntsc_rgb_t* gen_pixel( ntsc_to_rgb_t* ntsc, int ntsc_pos, int rescaled_pos, ntsc_rgb_t* out )
{
ntsc_to_rgb( ntsc, composite_border + ntsc_pos, ntsc->rgb [rgb_pad] );
rescale( ntsc->rgb [0], rescaled_size, ntsc->rescaled [1] );
sharpen( ntsc->rescaled [1], ntsc->sharpness, rescaled_size, ntsc->rescaled [0] );
{
short const* in = ntsc->rescaled [rescaled_pos];
int n = rgb_kernel_size;
while ( n-- )
{
*out++ = MAKE_KRGB( in [0], in [1], in [2] );
in += 3;
}
}
return out;
}
void atari_ntsc_init( atari_ntsc_t* emu, atari_ntsc_setup_t const* setup )
{
/* init pixel renderer */
int entry;
float burst_phase = (setup->burst_phase) * pi;
ntsc_to_rgb_t ntsc;
ntsc_to_rgb_init( &ntsc, setup, setup->hue * pi - burst_phase );
for ( entry = 0; entry < atari_ntsc_color_count; entry++ )
{
/*NTSC PHASE CONSTANTS.*/
float ntsc_phase_constant[16]={0,2.27,1.87,1.62,
1.22,0.62,-0.31,-0.855,
-1.18,-1.43,-1.63,-1.93,
-2.38,-3.43,2.52,2.07};
/*NTSC luma multipliers from gtia.pdf*/
float luma_mult[16]={
0.6941, 0.7091, 0.7241, 0.7401,
0.7560, 0.7741, 0.7931, 0.8121,
0.8260, 0.8470, 0.8700, 0.8930,
0.9160, 0.9420, 0.9690, 1.0000};
/* calculate yiq for color entry */
int color = entry >> 4;
float angle = burst_phase + ntsc_phase_constant[color];
float lumafactor = ( luma_mult[ entry & 0x0f] - luma_mult[0] )/( luma_mult[15] - luma_mult[0] );
float adj_lumafactor = pow(lumafactor, 1 +setup->gamma_adj);
float y = adj_lumafactor * rgb_unit;
float base_saturation = (color ? rgb_unit * 0.35f: 0.0f);
float saturation_ramp = setup->saturation_ramp;
float saturation = base_saturation * ( 1 - saturation_ramp*lumafactor );
float i = sin( angle ) * saturation;
float q = cos( angle ) * saturation;
ntsc_rgb_t* out = emu->table [entry];
y = y * ntsc.contrast + ntsc.brightness;
/* generate at four alignments with respect to output */
ntsc.composite [composite_border + 0] = i + y;
ntsc.composite [composite_border + 1] = q + y;
out = gen_pixel( &ntsc, 0, 0, out );
ntsc.composite [composite_border + 0] = 0;
ntsc.composite [composite_border + 1] = 0;
ntsc.composite [composite_border + 2] = i - y;
ntsc.composite [composite_border + 3] = q - y;
out = gen_pixel( &ntsc, 2, 2, out );
ntsc.composite [composite_border + 2] = 0;
ntsc.composite [composite_border + 3] = 0;
ntsc.composite [composite_border + 4] = i + y;
ntsc.composite [composite_border + 5] = q + y;
out = gen_pixel( &ntsc, 4, 4, out );
ntsc.composite [composite_border + 4] = 0;
ntsc.composite [composite_border + 5] = 0;
ntsc.composite [composite_border + 6] = i - y;
ntsc.composite [composite_border + 7] = q - y;
out = gen_pixel( &ntsc, 6, 6, out );
ntsc.composite [composite_border + 6] = 0;
ntsc.composite [composite_border + 7] = 0;
/* correct roundoff errors that would cause vertical bands in solid areas */
{
float r = y + i * ntsc.to_rgb [0] + q * ntsc.to_rgb [1];
float g = y + i * ntsc.to_rgb [2] + q * ntsc.to_rgb [3];
float b = y + i * ntsc.to_rgb [4] + q * ntsc.to_rgb [5];
ntsc_rgb_t correct = MAKE_KRGB( (int) r, (int) g, (int) b ) + MAKE_KMASK( 0x100 );
int i;
out = emu->table [entry];
for ( i = 0; i < rgb_kernel_size / 2; i++ )
{
/* sum as would occur when outputting run of pixels using same color,
but don't sum first kernel; the difference between this and the correct
color is what the first kernel's entry should be */
ntsc_rgb_t sum = out [(i+12)%14+14]+out[(i+10)%14+28]+out[(i+8)%14+42]+
out[i+7]+out [ i+ 5 +14]+out[ i+ 3 +28]+out[ i+1 +42];
out [i] = correct - sum;
}
}
}
Log_print("atari_ntsc_init(): sharpness:%f saturation:%f brightness:%f contrast:%f gaussian_factor:%f burst_phase:%f, hue:%f gamma_adj:%f saturation_ramp:%f\n",setup->sharpness,setup->saturation,setup->brightness,setup->contrast,setup->gaussian_factor,setup->burst_phase,setup->hue,setup->gamma_adj,setup->saturation_ramp);
}
void atari_ntsc_blit( atari_ntsc_t const* emu, unsigned char const* in, long in_pitch,
int width, int height, unsigned short* out, long out_pitch )
{
int const chunk_count = (width - 10) / 7;
long next_in_line = in_pitch - chunk_count * 4;
long next_out_line = out_pitch - (chunk_count + 1) * (7 * sizeof *out);
while ( height-- )
{
#define ENTRY( n ) emu->table [n]
ntsc_rgb_t const* k1 = ENTRY( 0 );
ntsc_rgb_t const* k2 = k1;
ntsc_rgb_t const* k3 = k1;
ntsc_rgb_t const* k4 = k1;
ntsc_rgb_t const* k5 = k4;
ntsc_rgb_t const* k6 = k4;
ntsc_rgb_t const* k7 = k4;
int n;
#if ATARI_NTSC_RGB_BITS == 16
#define TO_RGB( in ) ((in >> 11 & 0xF800) | (in >> 6 & 0x07C0) | (in >> 2 & 0x001F))
#elif ATARI_NTSC_RGB_BITS == 15
#define TO_RGB( in ) ((in >> 12 & 0x7C00) | (in >> 7 & 0x03E0) | (in >> 2 & 0x001F))
#endif
#define PIXEL( a ) {\
ntsc_rgb_t temp =\
k0 [a ] + k1 [(a+5)%7+14] + k2 [(a+3)%7+28] + k3 [(a+1)%7+42] +\
k4 [a+7] + k5 [(a+5)%7+21] + k6 [(a+3)%7+35] + k7 [(a+1)%7+49];\
if ( a ) out [a-1] = rgb;\
CLAMP_RGB( temp, 0 );\
rgb = TO_RGB( temp );\
}
for ( n = chunk_count; n; --n )
{
ntsc_rgb_t const* k0 = ENTRY( in [0] );
int rgb;
PIXEL( 0 );
PIXEL( 1 );
k5 = k1;
k1 = ENTRY( in [1] );
PIXEL( 2 );
PIXEL( 3 );
k6 = k2;
k2 = ENTRY( in [2] );
PIXEL( 4 );
PIXEL( 5 );
k7 = k3;
k3 = ENTRY( in [3] );
PIXEL( 6 );
out [6] = rgb;
k4 = k0;
in += 4;
out += 7;
}
{
ntsc_rgb_t const* k0 = ENTRY( 0 );
int rgb;
PIXEL( 0 );
PIXEL( 1 );
k5 = k1;
k1 = k0;
PIXEL( 2 );
PIXEL( 3 );
k6 = k2;
k2 = k0;
PIXEL( 4 );
PIXEL( 5 );
k7 = k3;
k3 = k0;
PIXEL( 6 );
k4 = k0;
out [6] = rgb;
out += 7;
PIXEL( 0 );
PIXEL( 1 );
k5 = k0;
PIXEL( 2 );
out [2] = rgb;
}
#undef PIXEL
in += next_in_line;
out = (unsigned short*) ((char*) out + next_out_line);
}
}
/* Atari800-specific: */
/* Adjust default values here */
atari_ntsc_setup_t atari_ntsc_setup = {
0.f, /* hue */
-0.1f, /* saturation */
0.f, /* contrast */
-0.1f, /* brightness */
-0.5f, /* sharpness */
-0.6f, /* burst phase */
0.f, /* gaussian factor */
-0.15, /* gamma adjustment */
0.25 /* satutration ramp */
};
int atari_ntsc_Initialise(int *argc, char *argv[])
{
int i, j;
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = 0; /* error, argument missing! */
if (strcmp(argv[i], "-ntsc_hue") == 0) {
if (i_a)
atari_ntsc_setup.hue = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_sat") == 0) {
if (i_a)
atari_ntsc_setup.saturation = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_cont") == 0) {
if (i_a)
atari_ntsc_setup.contrast = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_bright") == 0) {
if (i_a)
atari_ntsc_setup.brightness = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_sharp") == 0) {
if (i_a)
atari_ntsc_setup.sharpness = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_burst") == 0) {
if (i_a)
atari_ntsc_setup.burst_phase = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_gauss") == 0) {
if (i_a)
atari_ntsc_setup.gaussian_factor = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_gamma") == 0) {
if (i_a)
atari_ntsc_setup.gamma_adj = atof(argv[++i]);
else a_m = 1;
} else if (strcmp(argv[i], "-ntsc_ramp") == 0) {
if (i_a)
atari_ntsc_setup.saturation_ramp = atof(argv[++i]);
else a_m = 1;
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-ntsc_hue <n> Set NTSC hue -1..1 (default %.2g) (-ntsc_emu only)", atari_ntsc_setup.hue);
Log_print("\t-ntsc_sat <n> Set NTSC saturation (default %.2g) (-ntsc_emu only)", atari_ntsc_setup.saturation);
Log_print("\t-ntsc_cont <n> Set NTSC contrast (default %.2g) (-ntsc_emu only)", atari_ntsc_setup.contrast);
Log_print("\t-ntsc_bright <n> Set NTSC brightness (default %.2g) (-ntsc_emu only)", atari_ntsc_setup.brightness);
Log_print("\t-ntsc_sharp <n> Set NTSC sharpness (default %.2g) (-ntsc_emu only)", atari_ntsc_setup.sharpness);
Log_print("\t-ntsc_burst <n> Set NTSC burst phase -1..1 (artif colours)(def: %.2g)", atari_ntsc_setup.burst_phase);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_gauss <n> Set NTSC Gaussian factor (default %.2g)", atari_ntsc_setup.gaussian_factor);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_gamma <n> Set NTSC gamma adjustment (default %.2g)", atari_ntsc_setup.gamma_adj);
Log_print("\t (-ntsc_emu only)");
Log_print("\t-ntsc_ramp <n> Set NTSC saturation ramp factor (default %.2g)", atari_ntsc_setup.saturation_ramp);
Log_print("\t (-ntsc_emu only)");
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return 0;
}
}
*argc = j;
return 1;
}

View File

@@ -1,71 +0,0 @@
/* Atari GTIA NTSC composite video to RGB emulator/blitter */
#ifndef ATARI_NTSC_H
#define ATARI_NTSC_H
/* Picture parameters, ranging from -1.0 to 1.0 where 0.0 is normal. To easily
clear all fields, make it a static object then set whatever fields you want:
static snes_ntsc_setup_t setup;
setup.hue = ... */
typedef struct atari_ntsc_setup_t
{
float hue;
float saturation;
float contrast;
float brightness;
float sharpness;
float burst_phase; /* not in radians; -1.0 = -180 degrees, 1.0 = +180 degrees */
float gaussian_factor;
/* gamma adjustment */
float gamma_adj;
/* lower saturation for higher luma values */
float saturation_ramp;
} atari_ntsc_setup_t;
/* private */
enum { atari_ntsc_entry_size = 56 };
enum { atari_ntsc_color_count = 256 };
typedef unsigned long ntsc_rgb_t;
/*end private*/
/* Caller must allocate space for blitter data, which uses 56 KB of memory. */
typedef struct atari_ntsc_t
{
ntsc_rgb_t table [atari_ntsc_color_count] [atari_ntsc_entry_size];
} atari_ntsc_t;
/* Initialize and adjust parameters. Can be called multiple times on the same
atari_ntsc_t object. */
void atari_ntsc_init( struct atari_ntsc_t*, atari_ntsc_setup_t const* setup );
/* Blit one or more scanlines of Atari 8-bit palette values to 16-bit 5-6-5 RGB output.
For every 7 output pixels, reads approximately 4 source pixels. Use constants below for
definite input and output pixel counts. */
void atari_ntsc_blit( struct atari_ntsc_t const*, unsigned char const* atari_in, long in_pitch,
int out_width, int out_height, unsigned short* rgb_out, long out_pitch );
/* Useful values to use for output width and number of input pixels read */
enum {
atari_ntsc_min_out_width = 570, /* minimum width that doesn't cut off active area */
atari_ntsc_min_in_width = 320,
atari_ntsc_full_out_width = 598, /* room for 8-pixel left & right overscan borders */
atari_ntsc_full_in_width = 336
};
/* supports 16-bit and 15-bit RGB output */
#ifndef ATARI_NTSC_RGB_BITS
#define ATARI_NTSC_RGB_BITS 16
#endif
/* Atari800-specific: */
extern atari_ntsc_setup_t atari_ntsc_setup;
int atari_ntsc_Initialise(int *argc, char *argv[]);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,185 +0,0 @@
/*
* binload.c - load a binary executable file
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include "atari.h"
#include "binload.h"
#include "cpu.h"
#include "devices.h"
#include "esc.h"
#include "log.h"
#include "memory.h"
#include "sio.h"
int BINLOAD_start_binloading = FALSE;
int BINLOAD_loading_basic = 0;
FILE *BINLOAD_bin_file = NULL;
/* Read a word from file */
static int read_word(void)
{
UBYTE buf[2];
if (fread(buf, 1, 2, BINLOAD_bin_file) != 2) {
fclose(BINLOAD_bin_file);
BINLOAD_bin_file = NULL;
if (BINLOAD_start_binloading) {
BINLOAD_start_binloading = FALSE;
Log_print("binload: not valid BIN file");
return -1;
}
CPU_regPC = MEMORY_dGetWordAligned(0x2e0);
return -1;
}
return buf[0] + (buf[1] << 8);
}
/* Start or continue loading */
static void loader_cont(void)
{
if (BINLOAD_bin_file == NULL)
return;
if (BINLOAD_start_binloading) {
MEMORY_dPutByte(0x244, 0);
MEMORY_dPutByte(0x09, 1);
}
else
CPU_regS += 2; /* pop ESC code */
MEMORY_dPutByte(0x2e3, 0xd7);
do {
int temp;
UWORD from;
UWORD to;
do
temp = read_word();
while (temp == 0xffff);
if (temp < 0)
return;
from = (UWORD) temp;
temp = read_word();
if (temp < 0)
return;
to = (UWORD) temp;
if (BINLOAD_start_binloading) {
MEMORY_dPutWordAligned(0x2e0, from);
BINLOAD_start_binloading = FALSE;
}
to++;
do {
int byte = fgetc(BINLOAD_bin_file);
if (byte == EOF) {
fclose(BINLOAD_bin_file);
BINLOAD_bin_file = NULL;
CPU_regPC = MEMORY_dGetWordAligned(0x2e0);
if (MEMORY_dGetByte(0x2e3) != 0xd7) {
/* run INIT routine which RTSes directly to RUN routine */
CPU_regPC--;
MEMORY_dPutByte(0x0100 + CPU_regS--, CPU_regPC >> 8); /* high */
MEMORY_dPutByte(0x0100 + CPU_regS--, CPU_regPC & 0xff); /* low */
CPU_regPC = MEMORY_dGetWordAligned(0x2e2);
}
return;
}
MEMORY_PutByte(from, (UBYTE) byte);
from++;
} while (from != to);
} while (MEMORY_dGetByte(0x2e3) == 0xd7);
CPU_regS--;
ESC_Add((UWORD) (0x100 + CPU_regS), ESC_BINLOADER_CONT, loader_cont);
CPU_regS--;
MEMORY_dPutByte(0x0100 + CPU_regS--, 0x01); /* high */
MEMORY_dPutByte(0x0100 + CPU_regS, CPU_regS + 1); /* low */
CPU_regS--;
CPU_regPC = MEMORY_dGetWordAligned(0x2e2);
CPU_SetC;
MEMORY_dPutByte(0x0300, 0x31); /* for "Studio Dream" */
}
/* Fake boot sector to call loader_cont at boot time */
int BINLOAD_LoaderStart(UBYTE *buffer)
{
buffer[0] = 0x00; /* ignored */
buffer[1] = 0x01; /* one boot sector */
buffer[2] = 0x00; /* start at memory location 0x0700 */
buffer[3] = 0x07;
buffer[4] = 0x77; /* reset reboots (0xe477 = Atari OS Coldstart) */
buffer[5] = 0xe4;
buffer[6] = 0xf2; /* ESC */
buffer[7] = ESC_BINLOADER_CONT;
ESC_Add(0x706, ESC_BINLOADER_CONT, loader_cont);
return 'C';
}
/* Load BIN file, returns TRUE if ok */
int BINLOAD_Loader(const char *filename)
{
UBYTE buf[2];
if (BINLOAD_bin_file != NULL) { /* close previously open file */
fclose(BINLOAD_bin_file);
BINLOAD_bin_file = NULL;
BINLOAD_loading_basic = 0;
}
if (Atari800_machine_type == Atari800_MACHINE_5200) {
Log_print("binload: can't run Atari programs directly on the 5200");
return FALSE;
}
BINLOAD_bin_file = fopen(filename, "rb");
if (BINLOAD_bin_file == NULL) { /* open */
Log_print("binload: can't open \"%s\"", filename);
return FALSE;
}
/* Avoid "BOOT ERROR" when loading a BASIC program */
if (SIO_drive_status[0] == SIO_NO_DISK)
SIO_DisableDrive(1);
if (fread(buf, 1, 2, BINLOAD_bin_file) == 2) {
if (buf[0] == 0xff && buf[1] == 0xff) {
BINLOAD_start_binloading = TRUE; /* force SIO to call BINLOAD_LoaderStart at boot */
Atari800_Coldstart(); /* reboot */
return TRUE;
}
else if (buf[0] == 0 && buf[1] == 0) {
BINLOAD_loading_basic = BINLOAD_LOADING_BASIC_SAVED;
Devices_PatchOS();
Atari800_Coldstart();
return TRUE;
}
else if (buf[0] >= '0' && buf[0] <= '9') {
BINLOAD_loading_basic = BINLOAD_LOADING_BASIC_LISTED;
Devices_PatchOS();
Atari800_Coldstart();
return TRUE;
}
}
fclose(BINLOAD_bin_file);
BINLOAD_bin_file = NULL;
Log_print("binload: \"%s\" not recognized as a DOS or BASIC program", filename);
return FALSE;
}

View File

@@ -1,22 +0,0 @@
#ifndef BINLOAD_H_
#define BINLOAD_H_
#include <stdio.h> /* FILE */
#include "atari.h" /* UBYTE */
extern FILE *BINLOAD_bin_file;
int BINLOAD_Loader(const char *filename);
extern int BINLOAD_start_binloading;
extern int BINLOAD_loading_basic;
#define BINLOAD_LOADING_BASIC_SAVED 1
#define BINLOAD_LOADING_BASIC_LISTED 2
#define BINLOAD_LOADING_BASIC_LISTED_ATARI 3
#define BINLOAD_LOADING_BASIC_LISTED_CR 4
#define BINLOAD_LOADING_BASIC_LISTED_LF 5
#define BINLOAD_LOADING_BASIC_LISTED_CRLF 6
#define BINLOAD_LOADING_BASIC_LISTED_CR_OR_CRLF 7
#define BINLOAD_LOADING_BASIC_RUN 8
int BINLOAD_LoaderStart(UBYTE *buffer);
#endif /* BINLOAD_H_ */

View File

@@ -1,794 +0,0 @@
/*
* cartridge.c - cartridge emulation
*
* Copyright (C) 2001-2006 Piotr Fusik
* Copyright (C) 2001-2006 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "atari.h"
#include "binload.h" /* BINLOAD_loading_basic */
#include "cartridge.h"
#include "memory.h"
#include "pia.h"
#include "rtime.h"
#include "util.h"
#ifndef BASIC
#include "statesav.h"
#endif
int CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1] = {
0,
8, /* CARTRIDGE_STD_8 */
16, /* CARTRIDGE_STD_16 */
16, /* CARTRIDGE_OSS_16 */
32, /* CARTRIDGE_5200_32 */
32, /* CARTRIDGE_DB_32 */
16, /* CARTRIDGE_5200_EE_16 */
40, /* CARTRIDGE_5200_40 */
64, /* CARTRIDGE_WILL_64 */
64, /* CARTRIDGE_EXP_64 */
64, /* CARTRIDGE_DIAMOND_64 */
64, /* CARTRIDGE_SDX */
32, /* CARTRIDGE_XEGS_32 */
64, /* CARTRIDGE_XEGS_64 */
128, /* CARTRIDGE_XEGS_128 */
16, /* CARTRIDGE_OSS2_16 */
16, /* CARTRIDGE_5200_NS_16 */
128, /* CARTRIDGE_ATRAX_128 */
40, /* CARTRIDGE_BBSB_40 */
8, /* CARTRIDGE_5200_8 */
4, /* CARTRIDGE_5200_4 */
8, /* CARTRIDGE_RIGHT_8 */
32, /* CARTRIDGE_WILL_32 */
256, /* CARTRIDGE_XEGS_256 */
512, /* CARTRIDGE_XEGS_512 */
1024, /* CARTRIDGE_XEGS_1024 */
16, /* CARTRIDGE_MEGA_16 */
32, /* CARTRIDGE_MEGA_32 */
64, /* CARTRIDGE_MEGA_64 */
128, /* CARTRIDGE_MEGA_128 */
256, /* CARTRIDGE_MEGA_256 */
512, /* CARTRIDGE_MEGA_512 */
1024, /* CARTRIDGE_MEGA_1024 */
32, /* CARTRIDGE_SWXEGS_32 */
64, /* CARTRIDGE_SWXEGS_64 */
128, /* CARTRIDGE_SWXEGS_128 */
256, /* CARTRIDGE_SWXEGS_256 */
512, /* CARTRIDGE_SWXEGS_512 */
1024, /* CARTRIDGE_SWXEGS_1024 */
8, /* CARTRIDGE_PHOENIX_8 */
16, /* CARTRIDGE_BLIZZARD_16 */
128, /* CARTRIDGE_ATMAX_128 */
1024, /* CARTRIDGE_ATMAX_1024 */
128 /* CARTRIDGE_SDX_128 */
};
int CARTRIDGE_IsFor5200(int type)
{
switch (type) {
case CARTRIDGE_5200_32:
case CARTRIDGE_5200_EE_16:
case CARTRIDGE_5200_40:
case CARTRIDGE_5200_NS_16:
case CARTRIDGE_5200_8:
case CARTRIDGE_5200_4:
return TRUE;
default:
break;
}
return FALSE;
}
static UBYTE *cart_image = NULL; /* cartridge memory */
static char cart_filename[FILENAME_MAX];
int CARTRIDGE_type = CARTRIDGE_NONE;
static int bank;
/* DB_32, XEGS_32, XEGS_64, XEGS_128, XEGS_256, XEGS_512, XEGS_1024,
SWXEGS_32, SWXEGS_64, SWXEGS_128, SWXEGS_256, SWXEGS_512, SWXEGS_1024 */
static void set_bank_809F(int b, int main)
{
if (b != bank) {
if (b & 0x80) {
MEMORY_Cart809fDisable();
MEMORY_CartA0bfDisable();
}
else {
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image + b * 0x2000);
if (bank & 0x80)
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + main);
}
bank = b;
}
}
/* OSS_16, OSS2_16 */
static void set_bank_A0AF(int b, int main)
{
if (b != bank) {
if (b < 0)
MEMORY_CartA0bfDisable();
else {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xafff, cart_image + b * 0x1000);
if (bank < 0)
MEMORY_CopyROM(0xb000, 0xbfff, cart_image + main);
}
bank = b;
}
}
/* WILL_64, EXP_64, DIAMOND_64, SDX_64, WILL_32, ATMAX_128, ATMAX_1024,
ATRAX_128 */
static void set_bank_A0BF(int b, int n)
{
if (b != bank) {
if (b & n)
MEMORY_CartA0bfDisable();
else {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + (b & (n - 1)) * 0x2000);
}
bank = b;
}
}
static void set_bank_80BF(int b)
{
if (b != bank) {
if (b & 0x80) {
MEMORY_Cart809fDisable();
MEMORY_CartA0bfDisable();
}
else {
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0xbfff, cart_image + b * 0x4000);
}
bank = b;
}
}
/* an access (read or write) to D500-D5FF area */
static void access_D5(UWORD addr)
{
int b = bank;
switch (CARTRIDGE_type) {
case CARTRIDGE_OSS_16:
if (addr & 0x08)
b = -1;
else
switch (addr & 0x07) {
case 0x00:
case 0x01:
b = 0;
break;
case 0x03:
case 0x07:
b = 1;
break;
case 0x04:
case 0x05:
b = 2;
break;
/* case 0x02:
case 0x06: */
default:
break;
}
set_bank_A0AF(b, 0x3000);
break;
case CARTRIDGE_DB_32:
set_bank_809F(addr & 0x03, 0x6000);
break;
case CARTRIDGE_WILL_64:
set_bank_A0BF(addr, 8);
break;
case CARTRIDGE_WILL_32:
set_bank_A0BF(addr & 0xb, 8);
break;
case CARTRIDGE_EXP_64:
if ((addr & 0xf0) == 0x70)
set_bank_A0BF(addr ^ 7, 8);
break;
case CARTRIDGE_DIAMOND_64:
if ((addr & 0xf0) == 0xd0)
set_bank_A0BF(addr ^ 7, 8);
break;
case CARTRIDGE_SDX_64:
if ((addr & 0xf0) == 0xe0)
set_bank_A0BF(addr ^ 7, 8);
break;
case CARTRIDGE_SDX_128:
if ((addr & 0xe0) == 0xe0 && addr != bank) {
if (addr & 8)
MEMORY_CartA0bfDisable();
else {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff,
cart_image + (((addr & 7) + ((addr & 0x10) >> 1)) ^ 0xf) * 0x2000);
}
bank = addr;
}
break;
case CARTRIDGE_OSS2_16:
switch (addr & 0x09) {
case 0x00:
b = 1;
break;
case 0x01:
b = 3;
break;
case 0x08:
b = -1;
break;
case 0x09:
b = 2;
break;
}
set_bank_A0AF(b, 0x0000);
break;
case CARTRIDGE_PHOENIX_8:
MEMORY_CartA0bfDisable();
break;
case CARTRIDGE_BLIZZARD_16:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfDisable();
break;
case CARTRIDGE_ATMAX_128:
if ((addr & 0xe0) == 0)
set_bank_A0BF(addr, 16);
break;
case CARTRIDGE_ATMAX_1024:
set_bank_A0BF(addr, 128);
break;
default:
break;
}
}
/* a read from D500-D5FF area */
UBYTE CARTRIDGE_GetByte(UWORD addr)
{
if (RTIME_enabled && (addr == 0xd5b8 || addr == 0xd5b9))
return RTIME_GetByte();
access_D5(addr);
return 0xff;
}
/* a write to D500-D5FF area */
void CARTRIDGE_PutByte(UWORD addr, UBYTE byte)
{
if (RTIME_enabled && (addr == 0xd5b8 || addr == 0xd5b9)) {
RTIME_PutByte(byte);
return;
}
switch (CARTRIDGE_type) {
case CARTRIDGE_XEGS_32:
set_bank_809F(byte & 0x03, 0x6000);
break;
case CARTRIDGE_XEGS_64:
set_bank_809F(byte & 0x07, 0xe000);
break;
case CARTRIDGE_XEGS_128:
set_bank_809F(byte & 0x0f, 0x1e000);
break;
case CARTRIDGE_XEGS_256:
set_bank_809F(byte & 0x1f, 0x3e000);
break;
case CARTRIDGE_XEGS_512:
set_bank_809F(byte & 0x3f, 0x7e000);
break;
case CARTRIDGE_XEGS_1024:
set_bank_809F(byte & 0x7f, 0xfe000);
break;
case CARTRIDGE_ATRAX_128:
set_bank_A0BF(byte & 0x8f, 128);
break;
case CARTRIDGE_MEGA_16:
set_bank_80BF(byte & 0x80);
break;
case CARTRIDGE_MEGA_32:
set_bank_80BF(byte & 0x81);
break;
case CARTRIDGE_MEGA_64:
set_bank_80BF(byte & 0x83);
break;
case CARTRIDGE_MEGA_128:
set_bank_80BF(byte & 0x87);
break;
case CARTRIDGE_MEGA_256:
set_bank_80BF(byte & 0x8f);
break;
case CARTRIDGE_MEGA_512:
set_bank_80BF(byte & 0x9f);
break;
case CARTRIDGE_MEGA_1024:
set_bank_80BF(byte & 0xbf);
break;
case CARTRIDGE_SWXEGS_32:
set_bank_809F(byte & 0x83, 0x6000);
break;
case CARTRIDGE_SWXEGS_64:
set_bank_809F(byte & 0x87, 0xe000);
break;
case CARTRIDGE_SWXEGS_128:
set_bank_809F(byte & 0x8f, 0x1e000);
break;
case CARTRIDGE_SWXEGS_256:
set_bank_809F(byte & 0x9f, 0x3e000);
break;
case CARTRIDGE_SWXEGS_512:
set_bank_809F(byte & 0xbf, 0x7e000);
break;
case CARTRIDGE_SWXEGS_1024:
set_bank_809F(byte, 0xfe000);
break;
default:
access_D5(addr);
break;
}
}
/* special support of Bounty Bob on Atari5200 */
void CARTRIDGE_BountyBob1(UWORD addr)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x4ff6 && addr <= 0x4ff9) {
addr -= 0x4ff6;
MEMORY_CopyROM(0x4000, 0x4fff, cart_image + addr * 0x1000);
}
} else {
if (addr >= 0x8ff6 && addr <= 0x8ff9) {
addr -= 0x8ff6;
MEMORY_CopyROM(0x8000, 0x8fff, cart_image + addr * 0x1000);
}
}
}
void CARTRIDGE_BountyBob2(UWORD addr)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x5ff6 && addr <= 0x5ff9) {
addr -= 0x5ff6;
MEMORY_CopyROM(0x5000, 0x5fff, cart_image + 0x4000 + addr * 0x1000);
}
}
else {
if (addr >= 0x9ff6 && addr <= 0x9ff9) {
addr -= 0x9ff6;
MEMORY_CopyROM(0x9000, 0x9fff, cart_image + 0x4000 + addr * 0x1000);
}
}
}
#ifdef PAGED_ATTRIB
UBYTE CARTRIDGE_BountyBob1GetByte(UWORD addr)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x4ff6 && addr <= 0x4ff9) {
CARTRIDGE_BountyBob1(addr);
return 0;
}
} else {
if (addr >= 0x8ff6 && addr <= 0x8ff9) {
CARTRIDGE_BountyBob1(addr);
return 0;
}
}
return MEMORY_dGetByte(addr);
}
UBYTE CARTRIDGE_BountyBob2GetByte(UWORD addr)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x5ff6 && addr <= 0x5ff9) {
CARTRIDGE_BountyBob2(addr);
return 0;
}
} else {
if (addr >= 0x9ff6 && addr <= 0x9ff9) {
CARTRIDGE_BountyBob2(addr);
return 0;
}
}
return MEMORY_dGetByte(addr);
}
void CARTRIDGE_BountyBob1PutByte(UWORD addr, UBYTE value)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x4ff6 && addr <= 0x4ff9) {
CARTRIDGE_BountyBob1(addr);
}
} else {
if (addr >= 0x8ff6 && addr <= 0x8ff9) {
CARTRIDGE_BountyBob1(addr);
}
}
}
void CARTRIDGE_BountyBob2PutByte(UWORD addr, UBYTE value)
{
if (Atari800_machine_type == Atari800_MACHINE_5200) {
if (addr >= 0x5ff6 && addr <= 0x5ff9) {
CARTRIDGE_BountyBob2(addr);
}
} else {
if (addr >= 0x9ff6 && addr <= 0x9ff9) {
CARTRIDGE_BountyBob2(addr);
}
}
}
#endif
int CARTRIDGE_Checksum(const UBYTE *image, int nbytes)
{
int checksum = 0;
while (nbytes > 0) {
checksum += *image++;
nbytes--;
}
return checksum;
}
int CARTRIDGE_Insert(const char *filename)
{
FILE *fp;
int len;
int type;
UBYTE header[16];
/* remove currently inserted cart */
CARTRIDGE_Remove();
/* open file */
fp = fopen(filename, "rb");
if (fp == NULL)
return CARTRIDGE_CANT_OPEN;
/* check file length */
len = Util_flen(fp);
Util_rewind(fp);
/* Save Filename for state save */
strcpy(cart_filename, filename);
/* if full kilobytes, assume it is raw image */
if ((len & 0x3ff) == 0) {
/* alloc memory and read data */
cart_image = (UBYTE *) Util_malloc(len);
fread(cart_image, 1, len, fp);
fclose(fp);
/* find cart type */
CARTRIDGE_type = CARTRIDGE_NONE;
len >>= 10; /* number of kilobytes */
for (type = 1; type <= CARTRIDGE_LAST_SUPPORTED; type++)
if (CARTRIDGE_kb[type] == len) {
if (CARTRIDGE_type == CARTRIDGE_NONE)
CARTRIDGE_type = type;
else
return len; /* more than one cartridge type of such length - user must select */
}
if (CARTRIDGE_type != CARTRIDGE_NONE) {
CARTRIDGE_Start();
return 0; /* ok */
}
free(cart_image);
cart_image = NULL;
return CARTRIDGE_BAD_FORMAT;
}
/* if not full kilobytes, assume it is CART file */
fread(header, 1, 16, fp);
if ((header[0] == 'C') &&
(header[1] == 'A') &&
(header[2] == 'R') &&
(header[3] == 'T')) {
type = (header[4] << 24) |
(header[5] << 16) |
(header[6] << 8) |
header[7];
if (type >= 1 && type <= CARTRIDGE_LAST_SUPPORTED) {
int checksum;
len = CARTRIDGE_kb[type] << 10;
/* alloc memory and read data */
cart_image = (UBYTE *) Util_malloc(len);
fread(cart_image, 1, len, fp);
fclose(fp);
checksum = (header[8] << 24) |
(header[9] << 16) |
(header[10] << 8) |
header[11];
CARTRIDGE_type = type;
CARTRIDGE_Start();
return checksum == CARTRIDGE_Checksum(cart_image, len) ? 0 : CARTRIDGE_BAD_CHECKSUM;
}
}
fclose(fp);
return CARTRIDGE_BAD_FORMAT;
}
void CARTRIDGE_Remove(void)
{
CARTRIDGE_type = CARTRIDGE_NONE;
if (cart_image != NULL) {
free(cart_image);
cart_image = NULL;
}
CARTRIDGE_Start();
}
void CARTRIDGE_Start(void) {
if (Atari800_machine_type == Atari800_MACHINE_5200) {
MEMORY_SetROM(0x4ff6, 0x4ff9); /* disable Bounty Bob bank switching */
MEMORY_SetROM(0x5ff6, 0x5ff9);
switch (CARTRIDGE_type) {
case CARTRIDGE_5200_32:
MEMORY_CopyROM(0x4000, 0xbfff, cart_image);
break;
case CARTRIDGE_5200_EE_16:
MEMORY_CopyROM(0x4000, 0x5fff, cart_image);
MEMORY_CopyROM(0x6000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x2000);
break;
case CARTRIDGE_5200_40:
MEMORY_CopyROM(0x4000, 0x4fff, cart_image);
MEMORY_CopyROM(0x5000, 0x5fff, cart_image + 0x4000);
MEMORY_CopyROM(0x8000, 0x9fff, cart_image + 0x8000);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x8000);
#ifndef PAGED_ATTRIB
MEMORY_SetHARDWARE(0x4ff6, 0x4ff9);
MEMORY_SetHARDWARE(0x5ff6, 0x5ff9);
#else
MEMORY_readmap[0x4f] = CARTRIDGE_BountyBob1GetByte;
MEMORY_readmap[0x5f] = CARTRIDGE_BountyBob2GetByte;
MEMORY_writemap[0x4f] = CARTRIDGE_BountyBob1PutByte;
MEMORY_writemap[0x5f] = CARTRIDGE_BountyBob2PutByte;
#endif
break;
case CARTRIDGE_5200_NS_16:
MEMORY_CopyROM(0x8000, 0xbfff, cart_image);
break;
case CARTRIDGE_5200_8:
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image);
break;
case CARTRIDGE_5200_4:
MEMORY_CopyROM(0x8000, 0x8fff, cart_image);
MEMORY_CopyROM(0x9000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xafff, cart_image);
MEMORY_CopyROM(0xb000, 0xbfff, cart_image);
break;
default:
/* clear cartridge area so the 5200 will crash */
MEMORY_dFillMem(0x4000, 0, 0x8000);
break;
}
}
else {
switch (CARTRIDGE_type) {
case CARTRIDGE_STD_8:
case CARTRIDGE_PHOENIX_8:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image);
break;
case CARTRIDGE_STD_16:
case CARTRIDGE_BLIZZARD_16:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0xbfff, cart_image);
break;
case CARTRIDGE_OSS_16:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xafff, cart_image);
MEMORY_CopyROM(0xb000, 0xbfff, cart_image + 0x3000);
bank = 0;
break;
case CARTRIDGE_DB_32:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x6000);
bank = 0;
break;
case CARTRIDGE_WILL_64:
case CARTRIDGE_WILL_32:
case CARTRIDGE_EXP_64:
case CARTRIDGE_DIAMOND_64:
case CARTRIDGE_SDX_64:
case CARTRIDGE_SDX_128:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image);
bank = 0;
break;
case CARTRIDGE_XEGS_32:
case CARTRIDGE_SWXEGS_32:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x6000);
bank = 0;
break;
case CARTRIDGE_XEGS_64:
case CARTRIDGE_SWXEGS_64:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0xe000);
bank = 0;
break;
case CARTRIDGE_XEGS_128:
case CARTRIDGE_SWXEGS_128:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x1e000);
bank = 0;
break;
case CARTRIDGE_XEGS_256:
case CARTRIDGE_SWXEGS_256:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x3e000);
bank = 0;
break;
case CARTRIDGE_XEGS_512:
case CARTRIDGE_SWXEGS_512:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x7e000);
bank = 0;
break;
case CARTRIDGE_XEGS_1024:
case CARTRIDGE_SWXEGS_1024:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0xfe000);
bank = 0;
break;
case CARTRIDGE_OSS2_16:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xafff, cart_image + 0x1000);
MEMORY_CopyROM(0xb000, 0xbfff, cart_image);
bank = 0;
break;
case CARTRIDGE_ATRAX_128:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image);
bank = 0;
break;
case CARTRIDGE_BBSB_40:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0x8fff, cart_image);
MEMORY_CopyROM(0x9000, 0x9fff, cart_image + 0x4000);
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0x8000);
#ifndef PAGED_ATTRIB
MEMORY_SetHARDWARE(0x8ff6, 0x8ff9);
MEMORY_SetHARDWARE(0x9ff6, 0x9ff9);
#else
MEMORY_readmap[0x8f] = CARTRIDGE_BountyBob1GetByte;
MEMORY_readmap[0x9f] = CARTRIDGE_BountyBob2GetByte;
MEMORY_writemap[0x8f] = CARTRIDGE_BountyBob1PutByte;
MEMORY_writemap[0x9f] = CARTRIDGE_BountyBob2PutByte;
#endif
break;
case CARTRIDGE_RIGHT_8:
if (Atari800_machine_type == Atari800_MACHINE_OSA || Atari800_machine_type == Atari800_MACHINE_OSB) {
MEMORY_Cart809fEnable();
MEMORY_CopyROM(0x8000, 0x9fff, cart_image);
if ((!Atari800_disable_basic || BINLOAD_loading_basic) && MEMORY_have_basic) {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, MEMORY_basic);
break;
}
MEMORY_CartA0bfDisable();
break;
}
/* there's no right slot in XL/XE */
MEMORY_Cart809fDisable();
MEMORY_CartA0bfDisable();
break;
case CARTRIDGE_MEGA_16:
case CARTRIDGE_MEGA_32:
case CARTRIDGE_MEGA_64:
case CARTRIDGE_MEGA_128:
case CARTRIDGE_MEGA_256:
case CARTRIDGE_MEGA_512:
case CARTRIDGE_MEGA_1024:
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0xbfff, cart_image);
bank = 0;
break;
case CARTRIDGE_ATMAX_128:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image);
bank = 0;
break;
case CARTRIDGE_ATMAX_1024:
MEMORY_Cart809fDisable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, cart_image + 0xfe000);
bank = 0x7f;
break;
default:
MEMORY_Cart809fDisable();
if ((Atari800_machine_type == Atari800_MACHINE_OSA || Atari800_machine_type == Atari800_MACHINE_OSB)
&& (!Atari800_disable_basic || BINLOAD_loading_basic) && MEMORY_have_basic) {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, MEMORY_basic);
break;
}
MEMORY_CartA0bfDisable();
break;
}
}
}
#ifndef BASIC
void CARTRIDGE_StateRead(void)
{
int savedCartType = CARTRIDGE_NONE;
/* Read the cart type from the file. If there is no cart type, becaused we have
reached the end of the file, this will just default to CARTRIDGE_NONE */
StateSav_ReadINT(&savedCartType, 1);
if (savedCartType != CARTRIDGE_NONE) {
char filename[FILENAME_MAX];
StateSav_ReadFNAME(filename);
if (filename[0]) {
/* Insert the cartridge... */
if (CARTRIDGE_Insert(filename) >= 0) {
/* And set the type to the saved type, in case it was a raw cartridge image */
CARTRIDGE_type = savedCartType;
CARTRIDGE_Start();
}
}
}
}
void CARTRIDGE_StateSave(void)
{
/* Save the cartridge type, or CARTRIDGE_NONE if there isn't one...*/
StateSav_SaveINT(&CARTRIDGE_type, 1);
if (CARTRIDGE_type != CARTRIDGE_NONE) {
StateSav_SaveFNAME(cart_filename);
}
}
#endif

View File

@@ -1,81 +0,0 @@
#ifndef CARTRIDGE_H_
#define CARTRIDGE_H_
#include "config.h"
#include "atari.h"
#define CARTRIDGE_NONE 0
#define CARTRIDGE_STD_8 1
#define CARTRIDGE_STD_16 2
#define CARTRIDGE_OSS_16 3
#define CARTRIDGE_5200_32 4
#define CARTRIDGE_DB_32 5
#define CARTRIDGE_5200_EE_16 6
#define CARTRIDGE_5200_40 7
#define CARTRIDGE_WILL_64 8
#define CARTRIDGE_EXP_64 9
#define CARTRIDGE_DIAMOND_64 10
#define CARTRIDGE_SDX_64 11
#define CARTRIDGE_XEGS_32 12
#define CARTRIDGE_XEGS_64 13
#define CARTRIDGE_XEGS_128 14
#define CARTRIDGE_OSS2_16 15
#define CARTRIDGE_5200_NS_16 16
#define CARTRIDGE_ATRAX_128 17
#define CARTRIDGE_BBSB_40 18
#define CARTRIDGE_5200_8 19
#define CARTRIDGE_5200_4 20
#define CARTRIDGE_RIGHT_8 21
#define CARTRIDGE_WILL_32 22
#define CARTRIDGE_XEGS_256 23
#define CARTRIDGE_XEGS_512 24
#define CARTRIDGE_XEGS_1024 25
#define CARTRIDGE_MEGA_16 26
#define CARTRIDGE_MEGA_32 27
#define CARTRIDGE_MEGA_64 28
#define CARTRIDGE_MEGA_128 29
#define CARTRIDGE_MEGA_256 30
#define CARTRIDGE_MEGA_512 31
#define CARTRIDGE_MEGA_1024 32
#define CARTRIDGE_SWXEGS_32 33
#define CARTRIDGE_SWXEGS_64 34
#define CARTRIDGE_SWXEGS_128 35
#define CARTRIDGE_SWXEGS_256 36
#define CARTRIDGE_SWXEGS_512 37
#define CARTRIDGE_SWXEGS_1024 38
#define CARTRIDGE_PHOENIX_8 39
#define CARTRIDGE_BLIZZARD_16 40
#define CARTRIDGE_ATMAX_128 41
#define CARTRIDGE_ATMAX_1024 42
#define CARTRIDGE_SDX_128 43
#define CARTRIDGE_LAST_SUPPORTED 43
#define CARTRIDGE_MAX_SIZE (1024 * 1024)
extern int CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1];
extern int CARTRIDGE_type;
int CARTRIDGE_IsFor5200(int type);
int CARTRIDGE_Checksum(const UBYTE *image, int nbytes);
#define CARTRIDGE_CANT_OPEN -1 /* Can't open cartridge image file */
#define CARTRIDGE_BAD_FORMAT -2 /* Unknown cartridge format */
#define CARTRIDGE_BAD_CHECKSUM -3 /* Warning: bad CART checksum */
int CARTRIDGE_Insert(const char *filename);
void CARTRIDGE_Remove(void);
void CARTRIDGE_Start(void);
UBYTE CARTRIDGE_GetByte(UWORD addr);
void CARTRIDGE_PutByte(UWORD addr, UBYTE byte);
void CARTRIDGE_BountyBob1(UWORD addr);
void CARTRIDGE_BountyBob2(UWORD addr);
void CARTRIDGE_StateSave(void);
void CARTRIDGE_StateRead(void);
#ifdef PAGED_ATTRIB
UBYTE CARTRIDGE_BountyBob1GetByte(UWORD addr);
UBYTE CARTRIDGE_BountyBob2GetByte(UWORD addr);
void CARTRIDGE_BountyBob1PutByte(UWORD addr, UBYTE value);
void CARTRIDGE_BountyBob2PutByte(UWORD addr, UBYTE value);
#endif
#endif /* CARTRIDGE_H_ */

View File

@@ -1,752 +0,0 @@
/*
* cassette.c - cassette emulation
*
* Copyright (C) 2001 Piotr Fusik
* Copyright (C) 2001-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "atari.h"
#include "cpu.h"
#include "cassette.h"
#include "log.h"
#include "memory.h"
#include "sio.h"
#include "util.h"
#include "pokey.h"
#define MAX_BLOCKS 2048
static FILE *cassette_file = NULL;
static int cassette_isCAS;
UBYTE CASSETTE_buffer[4096];
static ULONG cassette_block_offset[MAX_BLOCKS];
static SLONG cassette_elapsedtime; /* elapsed time since begin of file */
/* in scanlines */
static SLONG cassette_savetime; /* helper for cas save */
static SLONG cassette_nextirqevent; /* timestamp of next irq in scanlines */
static char cassette_filename[FILENAME_MAX];
static char cassette_description[CASSETTE_DESCRIPTION_MAX];
static int cassette_current_blockbyte = 0;
static int cassette_current_block;
static int cassette_max_blockbytes = 0;
static int cassette_max_block = 0;
static int cassette_savefile = FALSE;
static int cassette_gapdelay = 0; /* in ms, includes leader and all gaps */
static int cassette_putdelay = 0; /* in ms, delay since last putbyte */
static int cassette_motor = 0;
static int cassette_baudrate = 600;
static int cassette_baudblock[MAX_BLOCKS];
int CASSETTE_hold_start_on_reboot = 0;
int CASSETTE_hold_start = 0;
int CASSETTE_press_space = 0;
static int eof_of_tape = 0;
typedef struct {
char identifier[4];
UBYTE length_lo;
UBYTE length_hi;
UBYTE aux_lo;
UBYTE aux_hi;
} CAS_Header;
/*
Just for remembering - CAS format in short:
It consists of chunks. Each chunk has a header, possibly followed by data.
If a header is unknown or unexpected it may be skipped by the length of the
header (8 bytes), and additionally the length given in the length-field(s).
There are (until now) 3 types of chunks:
-CAS file marker, has to be at begin of file - identifier "FUJI", length is
number of characters of an (optional) ascii-name (without trailing 0), aux
is always 0.
-baud rate selector - identifier "baud", length always 0, aux is rate in baud
(usually 600; one byte is 8 bits + startbit + stopbit, makes 60 bytes per
second).
-data record - identifier "data", length is length of the data block (usually
$84 as used by the OS), aux is length of mark tone (including leader and gaps)
just before the record data in milliseconds.
*/
int CASSETTE_Initialise(int *argc, char *argv[])
{
int i;
int j;
strcpy(cassette_filename, "None");
memset(cassette_description, 0, sizeof(cassette_description));
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = FALSE; /* error, argument missing! */
if (strcmp(argv[i], "-tape") == 0) {
if (i_a)
CASSETTE_Insert(argv[++i]);
else a_m = TRUE;
}
else if (strcmp(argv[i], "-boottape") == 0) {
if (i_a) {
CASSETTE_Insert(argv[++i]);
CASSETTE_hold_start = 1;
}
else a_m = TRUE;
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-tape <file> Insert cassette image");
Log_print("\t-boottape <file> Insert cassette image and boot it");
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return FALSE;
}
}
*argc = j;
return TRUE;
}
/* Gets information about the cassette image. Returns TRUE if ok.
To get information without attaching file, use:
char description[CASSETTE_DESCRIPTION_MAX];
int last_block;
int isCAS;
CASSETTE_CheckFile(filename, NULL, description, &last_block, &isCAS);
*/
int CASSETTE_CheckFile(const char *filename, FILE **fp, char *description, int *last_block, int *isCAS)
{
FILE *f;
CAS_Header header;
int blocks;
/* atm, no appending to existing cas files - too dangerous to data!
and will not work anyway without patched sio
f = fopen(filename, "rb+");
if (f == NULL) */
f = fopen(filename, "rb");
if (f == NULL)
return FALSE;
if (description)
memset(description, 0, CASSETTE_DESCRIPTION_MAX);
if (fread(&header, 1, 6, f) == 6
&& header.identifier[0] == 'F'
&& header.identifier[1] == 'U'
&& header.identifier[2] == 'J'
&& header.identifier[3] == 'I') {
/* CAS file */
UWORD length;
UWORD skip;
if (isCAS)
*isCAS = TRUE;
fseek(f, 2L, SEEK_CUR); /* ignore the aux bytes */
/* read or skip file description */
skip = length = header.length_lo + (header.length_hi << 8);
if (description) {
if (length < CASSETTE_DESCRIPTION_MAX)
skip = 0;
else
skip -= CASSETTE_DESCRIPTION_MAX - 1;
fread(description, 1, length - skip, f);
}
fseek(f, skip, SEEK_CUR);
/* count number of blocks */
blocks = 0;
cassette_baudblock[0]=600;
do {
/* chunk header is always 8 bytes */
if (fread(&header, 1, 8, f) != 8)
break;
if (header.identifier[0] == 'b'
&& header.identifier[1] == 'a'
&& header.identifier[2] == 'u'
&& header.identifier[3] == 'd') {
cassette_baudrate=header.aux_lo + (header.aux_hi << 8);
}
else if (header.identifier[0] == 'd'
&& header.identifier[1] == 'a'
&& header.identifier[2] == 't'
&& header.identifier[3] == 'a') {
blocks++;
if (fp) {
cassette_block_offset[blocks] = ftell(f) - 4;
cassette_baudblock[blocks] = cassette_baudrate;
}
}
length = header.length_lo + (header.length_hi << 8);
/* skip possibly present data block */
fseek(f, length, SEEK_CUR);
} while (blocks < MAX_BLOCKS);
}
else {
/* raw file */
int file_length = Util_flen(f);
blocks = ((file_length + 127) >> 7) + 1;
if (isCAS)
*isCAS = FALSE;
}
if (last_block)
*last_block = blocks;
/* if filelength is 0, then it is a savefile */
fseek(f,0L,SEEK_SET);
if (fread(&header, 1, 4, f) == 0) {
cassette_savefile = TRUE;
}
if (fp)
*fp = f;
else
fclose(f);
return TRUE;
}
/* Create CAS file header for saving data to tape */
int CASSETTE_CreateFile(const char *filename, FILE **fp, int *isCAS)
{
CAS_Header header;
memset(&header, 0, sizeof(header));
/* if no file pointer location was given, this function is senseless */
if (fp == NULL)
return FALSE;
/* close if open */
if (*fp != NULL)
fclose(*fp);
/* create new file */
*fp = fopen(filename, "wb");
if (*fp == NULL)
return FALSE;
/* write CAS-header */
{
size_t desc_len = strlen(cassette_description);
header.length_lo = (UBYTE) desc_len;
header.length_hi = (UBYTE) (desc_len >> 8);
if (fwrite("FUJI", 1, 4, *fp) == 4
&& fwrite(&header.length_lo, 1, 4, *fp) == 4
&& fwrite(cassette_description, 1, desc_len, *fp) == desc_len) {
/* ok */
}
else {
fclose(*fp);
*fp = NULL;
return FALSE;
}
}
memset(&header, 0, sizeof(header));
header.aux_lo = cassette_baudrate & 0xff; /* provisional: 600 baud */
header.aux_hi = cassette_baudrate >> 8;
if ((fwrite("baud", 1, 4, *fp) == 4)
&& (fwrite(&header.length_lo, 1, 4, *fp) == 4)) {
/* ok */
}
else {
fclose(*fp);
*fp = NULL;
return FALSE;
};
/* file is now a cassette file */
*isCAS = TRUE;
return TRUE;
}
int CASSETTE_Insert(const char *filename)
{
CASSETTE_Remove();
strcpy(cassette_filename, filename);
cassette_elapsedtime = 0;
cassette_savetime = 0;
cassette_nextirqevent = 0;
cassette_current_blockbyte = 0;
cassette_max_blockbytes = 0;
cassette_current_block = 1;
cassette_gapdelay = 0;
eof_of_tape = 0;
cassette_savefile = FALSE;
cassette_baudrate = 600;
return CASSETTE_CheckFile(filename, &cassette_file, cassette_description,
&cassette_max_block, &cassette_isCAS);
}
void CASSETTE_Remove(void)
{
if (cassette_file != NULL) {
/* save last block, ignore trailing space tone */
if ((cassette_current_blockbyte > 0) && cassette_savefile)
CASSETTE_Write(cassette_current_blockbyte);
fclose(cassette_file);
cassette_file = NULL;
}
cassette_max_block = 0;
strcpy(cassette_filename, "None");
memset(cassette_description, 0, sizeof(cassette_description));
}
/* Read a record by SIO-patch
returns block length (with checksum) */
static int ReadRecord_SIO(void)
{
int length = 0;
if (cassette_isCAS) {
CAS_Header header;
/* if waiting for gap was longer than gap of record, skip
atm there is no check if we start then inmidst a record */
int filegaptimes = 0;
while (cassette_gapdelay >= filegaptimes) {
if (cassette_current_block > cassette_max_block) {
length = -1;
break;
};
fseek(cassette_file, cassette_block_offset[cassette_current_block], SEEK_SET);
fread(&header.length_lo, 1, 4, cassette_file);
length = header.length_lo + (header.length_hi << 8);
/* add gaplength */
filegaptimes += header.aux_lo + (header.aux_hi << 8);
/* add time used by the data themselves
a byte is encoded into 10 bits */
filegaptimes += length * 10 * 1000 / cassette_baudblock[cassette_current_block];
fread(&CASSETTE_buffer[0], 1, length, cassette_file);
cassette_current_block++;
}
cassette_gapdelay = 0;
}
else {
length = 132;
CASSETTE_buffer[0] = 0x55;
CASSETTE_buffer[1] = 0x55;
if (cassette_current_block >= cassette_max_block) {
/* EOF record */
CASSETTE_buffer[2] = 0xfe;
memset(CASSETTE_buffer + 3, 0, 128);
}
else {
int bytes;
fseek(cassette_file, (cassette_current_block - 1) * 128, SEEK_SET);
bytes = fread(CASSETTE_buffer + 3, 1, 128, cassette_file);
if (bytes < 128) {
CASSETTE_buffer[2] = 0xfa; /* non-full record */
memset(CASSETTE_buffer + 3 + bytes, 0, 127 - bytes);
CASSETTE_buffer[0x82] = bytes;
}
else
CASSETTE_buffer[2] = 0xfc; /* full record */
}
CASSETTE_buffer[0x83] = SIO_ChkSum(CASSETTE_buffer, 0x83);
cassette_current_block++;
}
return length;
}
static UWORD WriteRecord(int len)
{
CAS_Header header;
memset(&header, 0, sizeof(header));
/* always append */
fseek(cassette_file, 0, SEEK_END);
/* write recordheader */
Util_strncpy(header.identifier, "data", 4);
header.length_lo = len & 0xFF;
header.length_hi = (len >> 8) & 0xFF;
header.aux_lo = cassette_gapdelay & 0xff;
header.aux_hi = (cassette_gapdelay >> 8) & 0xff;
cassette_gapdelay = 0;
fwrite(&header, 1, 8, cassette_file);
cassette_max_block++;
cassette_current_block++;
/* write record */
return fwrite(&CASSETTE_buffer, 1, len, cassette_file);
}
int CASSETTE_AddGap(int gaptime)
{
cassette_gapdelay += gaptime;
if (cassette_gapdelay < 0)
cassette_gapdelay = 0;
return cassette_gapdelay;
}
/* Indicates that a loading leader is expected by the OS */
void CASSETTE_LeaderLoad(void)
{
cassette_gapdelay = 9600;
/* registers for SETVBV: third system timer, ~0.1 sec */
CPU_regA = 3;
CPU_regX = 0;
CPU_regY = 5;
}
/* indicates that a save leader is written by the OS */
void CASSETTE_LeaderSave(void)
{
cassette_gapdelay = 19200;
/* registers for SETVBV: third system timer, ~0.1 sec */
CPU_regA = 3;
CPU_regX = 0;
CPU_regY = 5;
}
/* Read Cassette Record from Storage medium
returns size of data in buffer (atm equal with record size, but there
are protections with variable baud rates imaginable where a record
must be split and a baud chunk inserted inbetween) or -1 for error */
int CASSETTE_Read(void)
{
/* no file or blockpositions don't match anymore after saving */
if ((cassette_file == NULL) || (cassette_savefile == TRUE))
return -1;
if (cassette_current_block > cassette_max_block)
return -1; /* EOF */
return ReadRecord_SIO();
}
/* Write Cassette Record to Storage medium
length is size of the whole data with checksum(s)
returns really written bytes, -1 for error */
int CASSETTE_Write(int length)
{
/* there must be a filename given for saving */
if (strcmp(cassette_filename, "None") == 0)
return -1;
/* if file doesn't exist (or has no records), create the header */
if ((cassette_file == NULL || ftell(cassette_file) == 0) &&
(CASSETTE_CreateFile(cassette_filename,
&cassette_file,&cassette_isCAS) == FALSE))
return -1;
/* on a raw file, saving is denied because it can hold
only 1 file and could cause confusion */
if (cassette_isCAS == FALSE)
return -1;
/* save record (always appends to the end of file) */
cassette_savefile = TRUE;
return WriteRecord(length);
}
/* convert milliseconds to scanlines */
static SLONG MSToScanLines(int ms)
{
/* for PAL resolution, deviation in NTSC is negligible */
return 312*50*ms/1000;
}
/* Support to read a record by POKEY-registers
evals gap length
returns block length (with checksum) */
static int ReadRecord_POKEY(void)
{
int length = 0;
if (cassette_isCAS) {
CAS_Header header;
/* no file or blockpositions don't match anymore after saving */
if ((cassette_file == NULL) || (cassette_savefile == TRUE)) {
cassette_nextirqevent = -1;
length = -1;
return length;
}
/* if end of CAS file */
if (cassette_current_block > cassette_max_block){
cassette_nextirqevent = -1;
length = -1;
eof_of_tape = 1;
return length;
}
else {
fseek(cassette_file, cassette_block_offset[
cassette_current_block], SEEK_SET);
fread(&header.length_lo, 1, 4, cassette_file);
length = header.length_lo + (header.length_hi << 8);
/* eval total length as pregap + 1 byte */
cassette_nextirqevent = cassette_elapsedtime +
MSToScanLines(
header.aux_lo + (header.aux_hi << 8)
+ 10 * 1000 / cassette_baudblock[
cassette_current_block]);
/* read block into buffer */
fread(&CASSETTE_buffer[0], 1, length, cassette_file);
cassette_max_blockbytes = length;
cassette_current_blockbyte = 0;
cassette_current_block++;
}
}
else {
length = 132;
CASSETTE_buffer[0] = 0x55;
CASSETTE_buffer[1] = 0x55;
if (cassette_current_block >= cassette_max_block) {
/* EOF record */
CASSETTE_buffer[2] = 0xfe;
memset(CASSETTE_buffer + 3, 0, 128);
if (cassette_current_block > cassette_max_block) {
eof_of_tape = 1;
}
}
else {
int bytes;
fseek(cassette_file,
(cassette_current_block - 1) * 128, SEEK_SET);
bytes = fread(CASSETTE_buffer + 3, 1, 128,
cassette_file);
if (bytes < 128) {
CASSETTE_buffer[2] = 0xfa; /* non-full record */
memset(CASSETTE_buffer + 3 + bytes, 0,
127 - bytes);
CASSETTE_buffer[0x82] = bytes;
}
else
CASSETTE_buffer[2] = 0xfc; /* full record */
}
CASSETTE_buffer[0x83] = SIO_ChkSum(CASSETTE_buffer, 0x83);
/* eval time to first byte coming out of pokey */
if (cassette_current_block == 1) {
/* on first block, length includes a leader */
cassette_nextirqevent = cassette_elapsedtime +
MSToScanLines(19200
+ 10 * 1000 / 600); /* always 600 baud */
}
else {
cassette_nextirqevent = cassette_elapsedtime +
MSToScanLines(260
+ 10 * 1000 / 600); /* always 600 baud */
}
cassette_max_blockbytes = length;
cassette_current_blockbyte = 0;
cassette_current_block++;
}
return length;
}
/* sets the stamp of next irq and loads new record if necessary
adjust is a value to correction of time of next irq*/
static int SetNextByteTime_POKEY(int adjust)
{
int length = 0;
cassette_current_blockbyte += 1;
/* if there are still bytes in the buffer, take next byte */
if (cassette_current_blockbyte < cassette_max_blockbytes) {
cassette_nextirqevent = cassette_elapsedtime + adjust
+ MSToScanLines(10 * 1000 / (cassette_isCAS?cassette_baudblock[
cassette_current_block-1]:600));
return 0;
}
/* if buffer is exhausted, load next record */
length = ReadRecord_POKEY();
/* if failed, return -1 */
if (length == -1) {
cassette_nextirqevent = -1;
return -1;
}
cassette_nextirqevent += adjust;
return 0;
}
/* Get the byte for which the serial data ready int has been triggered */
int CASSETTE_GetByte(void)
{
/* there are programs which load 2 blocks as one */
return CASSETTE_buffer[cassette_current_blockbyte];
}
/* Check status of I/O-line
Mark tone and stop bit gives 1, start bit 0
$55 as data give 1,0,1,0,1,0,1,0 (sync to evaluate tape speed,
least significant bit first)
returns state of I/O-line as block.byte.bit */
int CASSETTE_IOLineStatus(void)
{
int bit = 0;
/* if motor off and EOF return always 1 (equivalent the mark tone) */
if ((cassette_motor == 0)
|| (eof_of_tape != 0)) {
return 1;
}
/* exam rate; if elapsed time > nextirq - duration of one byte */
if (cassette_elapsedtime >
(cassette_nextirqevent - 10 * 50 * 312 /
(cassette_isCAS?cassette_baudblock[cassette_current_block-1]:
600) + 1)) {
bit = (cassette_nextirqevent - cassette_elapsedtime)
/ (50 * 312 / (cassette_isCAS?cassette_baudblock[
cassette_current_block-1]:600));
}
else {
bit = 0;
}
/* if stopbit or out of range, return mark tone */
if ((bit <= 0) || (bit > 9))
return 1;
/* if start bit, return space tone */
if (bit == 9)
return 0;
/* eval tone to return */
return (CASSETTE_GetByte() >> (8 - bit)) & 1;
}
/* Get the delay to trigger the next interrupt
remark: The I/O-Line-status is also evaluated on this basis */
int CASSETTE_GetInputIRQDelay(void)
{
int timespan;
/* if no file or eof or motor off, return zero */
if ((cassette_file == NULL)
|| (eof_of_tape != 0)
|| (cassette_motor == 0)
|| (cassette_nextirqevent < 0)
|| cassette_savefile) {
return 0;
}
/* return time span */
timespan = cassette_nextirqevent - cassette_elapsedtime;
/* if timespan is negative, eval timespan to next byte */
if (timespan <= 0) {
if (SetNextByteTime_POKEY(0) == -1) {
return -1;
}
/* return time span */
timespan = cassette_nextirqevent - cassette_elapsedtime;
}
if (timespan < 40) {
timespan += ((312 * 50 - 1) / (cassette_isCAS?cassette_baudblock[
cassette_current_block-1]:600)) * 10;
}
/* if still negative, return "failed" */
if (timespan < 0) {
timespan = -1;
}
return timespan;
}
/* return if save file */
int CASSETTE_IsSaveFile(void)
{
return cassette_savefile;
}
/* put a byte into the cas file */
/* the block is being written at first putbyte of the subsequent block */
void CASSETTE_PutByte(int byte)
{
/* get time since last byte-put resp. motor on */
cassette_putdelay = 1000*(cassette_elapsedtime-cassette_savetime)/312/50;
/* subtract one byte-duration from put delay */
cassette_putdelay -= 1000 * 10 * (POKEY_AUDF[POKEY_CHAN3] + POKEY_AUDF[POKEY_CHAN4]*0x100)/895000;
/* if putdelay > 5 (ms) */
if (cassette_putdelay > 05) {
/* write previous block */
if (cassette_current_blockbyte > 0) {
CASSETTE_Write(cassette_current_blockbyte);
cassette_current_blockbyte = 0;
cassette_gapdelay = 0;
}
/* set new gap-time */
cassette_gapdelay += cassette_putdelay;
}
/* put byte into buffer */
CASSETTE_buffer[cassette_current_blockbyte] = byte;
cassette_current_blockbyte++;
/* set new last byte-put time */
cassette_savetime = cassette_elapsedtime;
}
/* set motor status
1 - on, 0 - off
remark: the real evaluation is done in AddScanLine*/
void CASSETTE_TapeMotor(int onoff)
{
if (cassette_file != NULL) {
if (cassette_savefile) { /* cas save */
if (onoff != cassette_motor) {
if (onoff == 0) {
/* get time since last byte-put resp. motor on */
cassette_putdelay = 1000*(cassette_elapsedtime-cassette_savetime)/312/50;
/* subtract one byte-duration from put delay */
cassette_putdelay -= 1000*10 * (POKEY_AUDF[POKEY_CHAN3] + POKEY_AUDF[POKEY_CHAN4]*0x100)/895000;
/* set putdelay non-negative */
if (cassette_putdelay < 0) {
cassette_putdelay = 0;
}
/* write block from buffer */
if (cassette_current_blockbyte > 0) {
CASSETTE_Write(cassette_current_blockbyte);
cassette_gapdelay = 0;
cassette_current_blockbyte = 0;
}
/* set new gap-time */
cassette_gapdelay += cassette_putdelay;
}
else {
/* motor on if it was off - restart gap time */
cassette_savetime = cassette_elapsedtime;
}
cassette_motor = onoff;
}
}
else {
cassette_motor = onoff;
/* restart gap time */
if (onoff == 1)
cassette_savetime = cassette_elapsedtime;
};
}
}
void CASSETTE_AddScanLine(void)
{
int tmp;
/* if motor on and a cassette file is opened, and not eof */
/* increment elapsed cassette time */
if (cassette_motor && (cassette_file != NULL)
&& ((eof_of_tape == 0) || cassette_savefile)) {
cassette_elapsedtime++;
/* only for loading: set next byte interrupt time */
/* valid cassette times are up to 870 baud, giving
a time span of 18 scanlines, so comparing with
-2 leaves a safe timespan for letting get the bit out
of the pokey */
if (((cassette_nextirqevent - cassette_elapsedtime) <= -2)
&& !cassette_savefile) {
tmp = SetNextByteTime_POKEY(-2);
}
}
}

View File

@@ -1,35 +0,0 @@
#ifndef CASSETTE_H_
#define CASSETTE_H_
#include <stdio.h> /* for FILE and FILENAME_MAX */
#include "atari.h" /* for UBYTE */
#define CASSETTE_DESCRIPTION_MAX 256
int CASSETTE_Initialise(int *argc, char *argv[]);
int CASSETTE_CheckFile(const char *filename, FILE **fp, char *description, int *last_block, int *isCAS);
int CASSETTE_CreateFile(const char *filename, FILE **fp, int *isCAS);
int CASSETTE_Insert(const char *filename);
void CASSETTE_Remove(void);
extern int CASSETTE_hold_start;
extern int CASSETTE_hold_start_on_reboot; /* preserve hold_start after reboot */
extern int CASSETTE_press_space;
int CASSETTE_AddGap(int gaptime);
void CASSETTE_LeaderLoad(void);
void CASSETTE_LeaderSave(void);
int CASSETTE_Read(void);
int CASSETTE_Write(int length);
int CASSETTE_IOLineStatus(void);
int CASSETTE_GetByte(void);
int CASSETTE_GetInputIRQDelay(void);
int CASSETTE_IsSaveFile(void);
void CASSETTE_PutByte(int byte);
void CASSETTE_TapeMotor(int onoff);
void CASSETTE_AddScanLine(void);
extern UBYTE CASSETTE_buffer[4096];
#endif /* CASSETTE_H_ */

View File

@@ -1,405 +0,0 @@
/*
* cfg.c - Emulator Configuration
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "atari.h"
#include <stdlib.h>
#include "cfg.h"
#include "devices.h"
#include "esc.h"
#include "log.h"
#include "memory.h"
#include "pbi.h"
#include "platform.h"
#include "pokeysnd.h"
#include "ui.h"
#include "util.h"
char CFG_osa_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
char CFG_osb_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
char CFG_xlxe_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
char CFG_5200_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
char CFG_basic_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
void CFG_FindROMImages(const char *directory, int only_if_not_set)
{
static char * const rom_filenames[5] = {
CFG_osa_filename,
CFG_osb_filename,
CFG_xlxe_filename,
CFG_5200_filename,
CFG_basic_filename
};
static const char * const common_filenames[] = {
"atariosa.rom", "atari_osa.rom", "atari_os_a.rom",
"ATARIOSA.ROM", "ATARI_OSA.ROM", "ATARI_OS_A.ROM",
NULL,
"atariosb.rom", "atari_osb.rom", "atari_os_b.rom",
"ATARIOSB.ROM", "ATARI_OSB.ROM", "ATARI_OS_B.ROM",
NULL,
"atarixlxe.rom", "atarixl.rom", "atari_xlxe.rom", "atari_xl_xe.rom",
"ATARIXLXE.ROM", "ATARIXL.ROM", "ATARI_XLXE.ROM", "ATARI_XL_XE.ROM",
NULL,
"atari5200.rom", "atar5200.rom", "5200.rom", "5200.bin", "atari_5200.rom",
"ATARI5200.ROM", "ATAR5200.ROM", "5200.ROM", "5200.BIN", "ATARI_5200.ROM",
NULL,
"ataribasic.rom", "ataribas.rom", "basic.rom", "atari_basic.rom",
"ATARIBASIC.ROM", "ATARIBAS.ROM", "BASIC.ROM", "ATARI_BASIC.ROM",
NULL
};
const char * const *common_filename = common_filenames;
int i;
for (i = 0; i < 5; i++) {
if (!only_if_not_set || Util_filenamenotset(rom_filenames[i])) {
do {
char full_filename[FILENAME_MAX];
Util_catpath(full_filename, directory, *common_filename);
if (Util_fileexists(full_filename)) {
strcpy(rom_filenames[i], full_filename);
break;
}
} while (*++common_filename != NULL);
}
while (*common_filename++ != NULL);
}
}
/* If another default path config path is defined use it
otherwise use the default one */
#ifndef DEFAULT_CFG_NAME
#define DEFAULT_CFG_NAME ".atari800.cfg"
#endif
#ifndef SYSTEM_WIDE_CFG_FILE
#define SYSTEM_WIDE_CFG_FILE "/etc/atari800.cfg"
#endif
static char rtconfig_filename[FILENAME_MAX];
int CFG_LoadConfig(const char *alternate_config_filename)
{
FILE *fp;
const char *fname = rtconfig_filename;
char string[256];
#ifndef BASIC
int was_obsolete_dir = FALSE;
#endif
#ifdef SUPPORTS_PLATFORM_CONFIGINIT
PLATFORM_ConfigInit();
#endif
/* if alternate config filename is passed then use it */
if (alternate_config_filename != NULL && *alternate_config_filename > 0) {
Util_strlcpy(rtconfig_filename, alternate_config_filename, FILENAME_MAX);
}
/* else use the default config name under the HOME folder */
else {
char *home = getenv("HOME");
if (home != NULL)
Util_catpath(rtconfig_filename, home, DEFAULT_CFG_NAME);
else
strcpy(rtconfig_filename, DEFAULT_CFG_NAME);
}
fp = fopen(fname, "r");
if (fp == NULL) {
Log_print("User config file '%s' not found.", rtconfig_filename);
#ifdef SYSTEM_WIDE_CFG_FILE
/* try system wide config file */
fname = SYSTEM_WIDE_CFG_FILE;
Log_print("Trying system wide config file: %s", fname);
fp = fopen(fname, "r");
#endif
if (fp == NULL) {
Log_print("No configuration file found, will create fresh one from scratch:");
return FALSE;
}
}
fgets(string, sizeof(string), fp);
Log_print("Using Atari800 config file: %s\nCreated by %s", fname, string);
while (fgets(string, sizeof(string), fp)) {
char *ptr;
Util_chomp(string);
ptr = strchr(string, '=');
if (ptr != NULL) {
*ptr++ = '\0';
Util_trim(string);
Util_trim(ptr);
if (strcmp(string, "OS/A_ROM") == 0)
Util_strlcpy(CFG_osa_filename, ptr, sizeof(CFG_osa_filename));
else if (strcmp(string, "OS/B_ROM") == 0)
Util_strlcpy(CFG_osb_filename, ptr, sizeof(CFG_osb_filename));
else if (strcmp(string, "XL/XE_ROM") == 0)
Util_strlcpy(CFG_xlxe_filename, ptr, sizeof(CFG_xlxe_filename));
else if (strcmp(string, "BASIC_ROM") == 0)
Util_strlcpy(CFG_basic_filename, ptr, sizeof(CFG_basic_filename));
else if (strcmp(string, "5200_ROM") == 0)
Util_strlcpy(CFG_5200_filename, ptr, sizeof(CFG_5200_filename));
#ifdef BASIC
else if (strcmp(string, "ATARI_FILES_DIR") == 0
|| strcmp(string, "SAVED_FILES_DIR") == 0
|| strcmp(string, "DISK_DIR") == 0 || strcmp(string, "ROM_DIR") == 0
|| strcmp(string, "EXE_DIR") == 0 || strcmp(string, "STATE_DIR") == 0)
/* do nothing */;
#else
else if (strcmp(string, "ATARI_FILES_DIR") == 0) {
if (UI_n_atari_files_dir >= UI_MAX_DIRECTORIES)
Log_print("All ATARI_FILES_DIR slots used!");
else
Util_strlcpy(UI_atari_files_dir[UI_n_atari_files_dir++], ptr, FILENAME_MAX);
}
else if (strcmp(string, "SAVED_FILES_DIR") == 0) {
if (UI_n_saved_files_dir >= UI_MAX_DIRECTORIES)
Log_print("All SAVED_FILES_DIR slots used!");
else
Util_strlcpy(UI_saved_files_dir[UI_n_saved_files_dir++], ptr, FILENAME_MAX);
}
else if (strcmp(string, "DISK_DIR") == 0 || strcmp(string, "ROM_DIR") == 0
|| strcmp(string, "EXE_DIR") == 0 || strcmp(string, "STATE_DIR") == 0) {
/* ignore blank and "." values */
if (ptr[0] != '\0' && (ptr[0] != '.' || ptr[1] != '\0'))
was_obsolete_dir = TRUE;
}
#endif
else if (strcmp(string, "H1_DIR") == 0)
Util_strlcpy(Devices_atari_h_dir[0], ptr, FILENAME_MAX);
else if (strcmp(string, "H2_DIR") == 0)
Util_strlcpy(Devices_atari_h_dir[1], ptr, FILENAME_MAX);
else if (strcmp(string, "H3_DIR") == 0)
Util_strlcpy(Devices_atari_h_dir[2], ptr, FILENAME_MAX);
else if (strcmp(string, "H4_DIR") == 0)
Util_strlcpy(Devices_atari_h_dir[3], ptr, FILENAME_MAX);
else if (strcmp(string, "HD_READ_ONLY") == 0)
Devices_h_read_only = Util_sscandec(ptr);
else if (strcmp(string, "PRINT_COMMAND") == 0) {
if (!Devices_SetPrintCommand(ptr))
Log_print("Unsafe PRINT_COMMAND ignored");
}
else if (strcmp(string, "SCREEN_REFRESH_RATIO") == 0)
Atari800_refresh_rate = Util_sscandec(ptr);
else if (strcmp(string, "DISABLE_BASIC") == 0)
Atari800_disable_basic = Util_sscanbool(ptr);
else if (strcmp(string, "ENABLE_SIO_PATCH") == 0) {
ESC_enable_sio_patch = Util_sscanbool(ptr);
}
else if (strcmp(string, "ENABLE_H_PATCH") == 0) {
Devices_enable_h_patch = Util_sscanbool(ptr);
}
else if (strcmp(string, "ENABLE_P_PATCH") == 0) {
Devices_enable_p_patch = Util_sscanbool(ptr);
}
else if (strcmp(string, "ENABLE_R_PATCH") == 0) {
Devices_enable_r_patch = Util_sscanbool(ptr);
}
else if (strcmp(string, "ENABLE_NEW_POKEY") == 0) {
#ifdef SOUND
POKEYSND_enable_new_pokey = Util_sscanbool(ptr);
#endif
}
else if (strcmp(string, "STEREO_POKEY") == 0) {
#ifdef STEREO_SOUND
POKEYSND_stereo_enabled = Util_sscanbool(ptr);
#endif
}
else if (strcmp(string, "SPEAKER_SOUND") == 0) {
#ifdef CONSOLE_SOUND
POKEYSND_console_sound_enabled = Util_sscanbool(ptr);
#endif
}
else if (strcmp(string, "SERIO_SOUND") == 0) {
#ifdef SERIO_SOUND
POKEYSND_serio_sound_enabled = Util_sscanbool(ptr);
#endif
}
else if (strcmp(string, "MACHINE_TYPE") == 0) {
if (strcmp(ptr, "Atari OS/A") == 0)
Atari800_machine_type = Atari800_MACHINE_OSA;
else if (strcmp(ptr, "Atari OS/B") == 0)
Atari800_machine_type = Atari800_MACHINE_OSB;
else if (strcmp(ptr, "Atari XL/XE") == 0)
Atari800_machine_type = Atari800_MACHINE_XLXE;
else if (strcmp(ptr, "Atari 5200") == 0)
Atari800_machine_type = Atari800_MACHINE_5200;
else
Log_print("Invalid machine type: %s", ptr);
}
else if (strcmp(string, "RAM_SIZE") == 0) {
if (strcmp(ptr, "16") == 0)
MEMORY_ram_size = 16;
else if (strcmp(ptr, "48") == 0)
MEMORY_ram_size = 48;
else if (strcmp(ptr, "52") == 0)
MEMORY_ram_size = 52;
else if (strcmp(ptr, "64") == 0)
MEMORY_ram_size = 64;
else if (strcmp(ptr, "128") == 0)
MEMORY_ram_size = 128;
else if (strcmp(ptr, "192") == 0)
MEMORY_ram_size = 192;
else if (strcmp(ptr, "320 (RAMBO)") == 0)
MEMORY_ram_size = MEMORY_RAM_320_RAMBO;
else if (strcmp(ptr, "320 (COMPY SHOP)") == 0)
MEMORY_ram_size = MEMORY_RAM_320_COMPY_SHOP;
else if (strcmp(ptr, "576") == 0)
MEMORY_ram_size = 576;
else if (strcmp(ptr, "1088") == 0)
MEMORY_ram_size = 1088;
else
Log_print("Invalid RAM size: %s", ptr);
}
else if (strcmp(string, "DEFAULT_TV_MODE") == 0) {
if (strcmp(ptr, "PAL") == 0)
Atari800_tv_mode = Atari800_TV_PAL;
else if (strcmp(ptr, "NTSC") == 0)
Atari800_tv_mode = Atari800_TV_NTSC;
else
Log_print("Invalid TV Mode: %s", ptr);
}
/* Add module-specific configurations here */
else if (PBI_ReadConfig(string,ptr)) {
}
else {
#ifdef SUPPORTS_PLATFORM_CONFIGURE
if (!PLATFORM_Configure(string, ptr)) {
Log_print("Unrecognized variable or bad parameters: '%s=%s'", string, ptr);
}
#else
Log_print("Unrecognized variable: %s", string);
#endif
}
}
else {
Log_print("Ignored config line: %s", string);
}
}
fclose(fp);
#ifndef BASIC
if (was_obsolete_dir) {
Log_print(
"DISK_DIR, ROM_DIR, EXE_DIR and STATE_DIR configuration options\n"
"are no longer supported. Please use ATARI_FILES_DIR\n"
"and SAVED_FILES_DIR in your Atari800 configuration file.");
}
#endif
return TRUE;
}
int CFG_WriteConfig(void)
{
FILE *fp;
int i;
static const char * const machine_type_string[4] = {
"OS/A", "OS/B", "XL/XE", "5200"
};
fp = fopen(rtconfig_filename, "w");
if (fp == NULL) {
perror(rtconfig_filename);
Log_print("Cannot write to config file: %s", rtconfig_filename);
return FALSE;
}
Log_print("Writing config file: %s", rtconfig_filename);
fprintf(fp, "%s\n", Atari800_TITLE);
fprintf(fp, "OS/A_ROM=%s\n", CFG_osa_filename);
fprintf(fp, "OS/B_ROM=%s\n", CFG_osb_filename);
fprintf(fp, "XL/XE_ROM=%s\n", CFG_xlxe_filename);
fprintf(fp, "BASIC_ROM=%s\n", CFG_basic_filename);
fprintf(fp, "5200_ROM=%s\n", CFG_5200_filename);
#ifndef BASIC
for (i = 0; i < UI_n_atari_files_dir; i++)
fprintf(fp, "ATARI_FILES_DIR=%s\n", UI_atari_files_dir[i]);
for (i = 0; i < UI_n_saved_files_dir; i++)
fprintf(fp, "SAVED_FILES_DIR=%s\n", UI_saved_files_dir[i]);
#endif
for (i = 0; i < 4; i++)
fprintf(fp, "H%c_DIR=%s\n", '1' + i, Devices_atari_h_dir[i]);
fprintf(fp, "HD_READ_ONLY=%d\n", Devices_h_read_only);
#ifdef HAVE_SYSTEM
fprintf(fp, "PRINT_COMMAND=%s\n", Devices_print_command);
#endif
#ifndef BASIC
fprintf(fp, "SCREEN_REFRESH_RATIO=%d\n", Atari800_refresh_rate);
#endif
fprintf(fp, "MACHINE_TYPE=Atari %s\n", machine_type_string[Atari800_machine_type]);
fprintf(fp, "RAM_SIZE=");
switch (MEMORY_ram_size) {
case MEMORY_RAM_320_RAMBO:
fprintf(fp, "320 (RAMBO)\n");
break;
case MEMORY_RAM_320_COMPY_SHOP:
fprintf(fp, "320 (COMPY SHOP)\n");
break;
default:
fprintf(fp, "%d\n", MEMORY_ram_size);
break;
}
fprintf(fp, (Atari800_tv_mode == Atari800_TV_PAL) ? "DEFAULT_TV_MODE=PAL\n" : "DEFAULT_TV_MODE=NTSC\n");
fprintf(fp, "DISABLE_BASIC=%d\n", Atari800_disable_basic);
fprintf(fp, "ENABLE_SIO_PATCH=%d\n", ESC_enable_sio_patch);
fprintf(fp, "ENABLE_H_PATCH=%d\n", Devices_enable_h_patch);
fprintf(fp, "ENABLE_P_PATCH=%d\n", Devices_enable_p_patch);
#ifdef R_IO_DEVICE
fprintf(fp, "ENABLE_R_PATCH=%d\n", Devices_enable_r_patch);
#endif
#ifdef SOUND
fprintf(fp, "ENABLE_NEW_POKEY=%d\n", POKEYSND_enable_new_pokey);
#ifdef STEREO_SOUND
fprintf(fp, "STEREO_POKEY=%d\n", POKEYSND_stereo_enabled);
#endif
#ifdef CONSOLE_SOUND
fprintf(fp, "SPEAKER_SOUND=%d\n", POKEYSND_console_sound_enabled);
#endif
#ifdef SERIO_SOUND
fprintf(fp, "SERIO_SOUND=%d\n", POKEYSND_serio_sound_enabled);
#endif
#endif /* SOUND */
/* Add module-specific configurations here */
PBI_WriteConfig(fp);
#ifdef SUPPORTS_PLATFORM_CONFIGSAVE
PLATFORM_ConfigSave(fp);
#endif
fclose(fp);
return TRUE;
}

View File

@@ -1,22 +0,0 @@
#ifndef CFG_H_
#define CFG_H_
/* Checks for "popular" filenames of ROM images in the specified directory
and sets CFG_*_filename to the ones found.
If only_if_not_set is TRUE, then CFG_*_filename is modified only when
Util_filenamenotset() is TRUE for it. */
void CFG_FindROMImages(const char *directory, int only_if_not_set);
/* Load Atari800 text configuration file. */
int CFG_LoadConfig(const char *alternate_config_filename);
/* Writes Atari800 text configuration file. */
int CFG_WriteConfig(void);
/* Paths to ROM images. */
extern char CFG_osa_filename[FILENAME_MAX];
extern char CFG_osb_filename[FILENAME_MAX];
extern char CFG_xlxe_filename[FILENAME_MAX];
extern char CFG_5200_filename[FILENAME_MAX];
extern char CFG_basic_filename[FILENAME_MAX];
#endif /* CFG_H_ */

View File

@@ -1,443 +0,0 @@
/*
* colours.c - Atari colour palette
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2009 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <string.h> /* for strcmp() */
#include <math.h>
#include <stdlib.h>
#include "atari.h"
#include "colours.h"
#include "log.h"
#include "util.h"
#include "platform.h"
#ifdef __PLUS
#include "display_win.h"
#include "misc_win.h"
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define PALETTE_R(x,c) ((UBYTE) (c[x] >> 16))
#define PALETTE_G(x,c) ((UBYTE) (c[x] >> 8))
#define PALETTE_B(x,c) ((UBYTE) c[x])
#define PALETTE_Y(x,c) (0.30 * PALETTE_R(x,c) + 0.59 * PALETTE_G(x,c) + 0.11 * PALETTE_B(x,c))
int *Colours_table;
static int colortable_ntsc[256] = {
0x000000, 0x101010, 0x1f1f1f, 0x2f2f2f,
0x3e3e3e, 0x4e4e4e, 0x5e5e5e, 0x6e6e6e,
0x797979, 0x8a8a8a, 0x9c9c9c, 0xadadad,
0xbfbfbf, 0xd2d2d2, 0xe6e6e6, 0xfcfcfc,
0x110900, 0x241d00, 0x342c00, 0x433c00,
0x514a00, 0x615a00, 0x716a00, 0x817a00,
0x8c850c, 0x9c951f, 0xaea734, 0xbfb847,
0xd0c95b, 0xe3dc71, 0xf6f087, 0xffffa1,
0x2a0000, 0x3d0b00, 0x4c1b00, 0x5b2b00,
0x693a00, 0x794a00, 0x885a04, 0x976a16,
0xa27522, 0xb28634, 0xc39848, 0xd4aa5c,
0xe4bb6f, 0xf7cf84, 0xffe29a, 0xfff9b3,
0x360000, 0x490100, 0x581100, 0x672100,
0x752f00, 0x844008, 0x93501a, 0xa2602b,
0xad6c37, 0xbd7d49, 0xcd8f5c, 0xdea16f,
0xeeb282, 0xffc697, 0xffdaac, 0xfff1c4,
0x420000, 0x540000, 0x630204, 0x721214,
0x802123, 0x8f3233, 0x9e4244, 0xad5354,
0xb75e60, 0xc77071, 0xd88284, 0xe89496,
0xf8a6a7, 0xffbabb, 0xffced0, 0xffe5e7,
0x3e002a, 0x51003e, 0x60004d, 0x6f065c,
0x7d156a, 0x8c2679, 0x9b3789, 0xaa4798,
0xb453a3, 0xc464b3, 0xd577c4, 0xe589d4,
0xf59ce5, 0xffb0f7, 0xffc4ff, 0xffdcff,
0x0f0077, 0x220089, 0x320097, 0x410fa5,
0x501eb2, 0x5f2ec1, 0x6f3fcf, 0x7f50dd,
0x8a5be7, 0x9a6df5, 0xac7fff, 0xbd91ff,
0xcea3ff, 0xe1b7ff, 0xf4ccff, 0xffe3ff,
0x000076, 0x000288, 0x0c1297, 0x1c22a5,
0x2b31b2, 0x3b41c0, 0x4c51ce, 0x5c61dc,
0x686de6, 0x797ef5, 0x8b90ff, 0x9da2ff,
0xafb3ff, 0xc2c7ff, 0xd6dbff, 0xedf2ff,
0x000065, 0x001077, 0x002086, 0x082f94,
0x173ea1, 0x284eb0, 0x395ebe, 0x496ecc,
0x5579d7, 0x668ae6, 0x799cf6, 0x8baeff,
0x9ebfff, 0xb2d2ff, 0xc6e6ff, 0xddfcff,
0x00074f, 0x001b62, 0x002a71, 0x003a7f,
0x0b488d, 0x1b589c, 0x2c68ab, 0x3d78b9,
0x4983c4, 0x5b94d3, 0x6ea5e3, 0x80b7f3,
0x93c8ff, 0xa7dbff, 0xbceeff, 0xd3ffff,
0x000f3b, 0x00234e, 0x00325d, 0x00426c,
0x035079, 0x146089, 0x257098, 0x367fa7,
0x428ab1, 0x539bc1, 0x67acd2, 0x79bee2,
0x8ccff2, 0xa0e1ff, 0xb5f5ff, 0xcdffff,
0x001a17, 0x002d2b, 0x003d3a, 0x004c49,
0x005a58, 0x0c6a67, 0x1e7a77, 0x2f8987,
0x3b9492, 0x4da4a2, 0x60b6b3, 0x73c7c4,
0x86d7d5, 0x9aeae8, 0xb0fdfb, 0xc8ffff,
0x002500, 0x003800, 0x004803, 0x005713,
0x006522, 0x0d7432, 0x1e8443, 0x2f9353,
0x3b9e5f, 0x4dae70, 0x60bf83, 0x73d095,
0x86e0a7, 0x9bf3bb, 0xb0ffcf, 0xc8ffe6,
0x001e00, 0x003100, 0x0c4100, 0x1c5000,
0x2a5e00, 0x3b6e00, 0x4b7d00, 0x5b8d00,
0x67970c, 0x78a81f, 0x8ab933, 0x9cca47,
0xaedb5b, 0xc2ed71, 0xd6ff87, 0xedffa0,
0x001300, 0x132600, 0x233600, 0x324500,
0x415400, 0x516300, 0x617300, 0x718300,
0x7c8e08, 0x8d9e1b, 0x9fb02f, 0xb0c143,
0xc1d257, 0xd5e46d, 0xe8f883, 0xfeff9d,
0x1e0000, 0x311400, 0x412400, 0x503300,
0x5e4200, 0x6e5200, 0x7d6200, 0x8d7209,
0x977d15, 0xa88e28, 0xb9a03c, 0xcab150,
0xdbc263, 0xedd679, 0xffe98f, 0xffffa8
};
static int colortable_pal[256] = {
0x2d2d2d, 0x3b3b3b, 0x494949, 0x575757,
0x656565, 0x737373, 0x818181, 0x8f8f8f,
0x9d9d9d, 0xababab, 0xb9b9b9, 0xc7c7c7,
0xd5d5d5, 0xe3e3e3, 0xf1f1f1, 0xffffff,
0x5c2300, 0x6a3100, 0x783f00, 0x864d0a,
0x945b18, 0xa26926, 0xb07734, 0xbe8542,
0xcc9350, 0xdaa15e, 0xe8af6c, 0xf6bd7a,
0xffcb88, 0xffd996, 0xffe7a4, 0xfff5b2,
0x691409, 0x772217, 0x853025, 0x933e33,
0xa14c41, 0xaf5a4f, 0xbd685d, 0xcb766b,
0xd98479, 0xe79287, 0xf5a095, 0xffaea3,
0xffbcb1, 0xffcabf, 0xffd8cd, 0xffe6db,
0x6c0a38, 0x7a1846, 0x882654, 0x963462,
0xa44270, 0xb2507e, 0xc05e8c, 0xce6c9a,
0xdc7aa8, 0xea88b6, 0xf896c4, 0xffa4d2,
0xffb2e0, 0xffc0ee, 0xffcefc, 0xffdcff,
0x640565, 0x721373, 0x802181, 0x8e2f8f,
0x9c3d9d, 0xaa4bab, 0xb859b9, 0xc667c7,
0xd475d5, 0xe283e3, 0xf091f1, 0xfe9fff,
0xffadff, 0xffbbff, 0xffc9ff, 0xffd7ff,
0x520789, 0x601597, 0x6e23a5, 0x7c31b3,
0x8a3fc1, 0x984dcf, 0xa65bdd, 0xb469eb,
0xc277f9, 0xd085ff, 0xde93ff, 0xeca1ff,
0xfaafff, 0xffbdff, 0xffcbff, 0xffd9ff,
0x3a109c, 0x481eaa, 0x562cb8, 0x643ac6,
0x7248d4, 0x8056e2, 0x8e64f0, 0x9c72fe,
0xaa80ff, 0xb88eff, 0xc69cff, 0xd4aaff,
0xe2b8ff, 0xf0c6ff, 0xfed4ff, 0xffe2ff,
0x1f1e9c, 0x2d2caa, 0x3b3ab8, 0x4948c6,
0x5756d4, 0x6564e2, 0x7372f0, 0x8180fe,
0x8f8eff, 0x9d9cff, 0xabaaff, 0xb9b8ff,
0xc7c6ff, 0xd5d4ff, 0xe3e2ff, 0xf1f0ff,
0x072e89, 0x153c97, 0x234aa5, 0x3158b3,
0x3f66c1, 0x4d74cf, 0x5b82dd, 0x6990eb,
0x779ef9, 0x85acff, 0x93baff, 0xa1c8ff,
0xafd6ff, 0xbde4ff, 0xcbf2ff, 0xd9ffff,
0x003e65, 0x034c73, 0x115a81, 0x1f688f,
0x2d769d, 0x3b84ab, 0x4992b9, 0x57a0c7,
0x65aed5, 0x73bce3, 0x81caf1, 0x8fd8ff,
0x9de6ff, 0xabf4ff, 0xb9ffff, 0xc7ffff,
0x004b38, 0x005946, 0x096754, 0x177562,
0x258370, 0x33917e, 0x419f8c, 0x4fad9a,
0x5dbba8, 0x6bc9b6, 0x79d7c4, 0x87e5d2,
0x95f3e0, 0xa3ffee, 0xb1fffc, 0xbfffff,
0x005209, 0x006017, 0x0c6e25, 0x1a7c33,
0x288a41, 0x36984f, 0x44a65d, 0x52b46b,
0x60c279, 0x6ed087, 0x7cde95, 0x8aeca3,
0x98fab1, 0xa6ffbf, 0xb4ffcd, 0xc2ffdb,
0x005300, 0x0b6100, 0x196f00, 0x277d0a,
0x358b18, 0x439926, 0x51a734, 0x5fb542,
0x6dc350, 0x7bd15e, 0x89df6c, 0x97ed7a,
0xa5fb88, 0xb3ff96, 0xc1ffa4, 0xcfffb2,
0x134e00, 0x215c00, 0x2f6a00, 0x3d7800,
0x4b8600, 0x59940b, 0x67a219, 0x75b027,
0x83be35, 0x91cc43, 0x9fda51, 0xade85f,
0xbbf66d, 0xc9ff7b, 0xd7ff89, 0xe5ff97,
0x2d4300, 0x3b5100, 0x495f00, 0x576d00,
0x657b00, 0x738901, 0x81970f, 0x8fa51d,
0x9db32b, 0xabc139, 0xb9cf47, 0xc7dd55,
0xd5eb63, 0xe3f971, 0xf1ff7f, 0xffff8d,
0x463300, 0x544100, 0x624f00, 0x705d00,
0x7e6b00, 0x8c790b, 0x9a8719, 0xa89527,
0xb6a335, 0xc4b143, 0xd2bf51, 0xe0cd5f,
0xeedb6d, 0xfce97b, 0xfff789, 0xffff97
};
void Colours_SetRGB(int i, int r, int g, int b, int *colortable_ptr)
{
if (r < 0)
r = 0;
else if (r > 255)
r = 255;
if (g < 0)
g = 0;
else if (g > 255)
g = 255;
if (b < 0)
b = 0;
else if (b > 255)
b = 255;
colortable_ptr[i] = (r << 16) + (g << 8) + b;
}
int Colours_Read(const char *filename, int *colortable_ptr)
{
FILE *fp;
int i;
fp = fopen(filename, "rb");
if (fp == NULL)
return FALSE;
for (i = 0; i < 256; i++) {
int j;
colortable_ptr[i] = 0;
for (j = 16; j >= 0; j -= 8) {
int c = fgetc(fp);
if (c == EOF) {
fclose(fp);
return FALSE;
}
colortable_ptr[i] |= c << j;
}
}
fclose(fp);
return TRUE;
}
void Colours_Generate(int black, int white, int colshift, int *colortable_ptr)
{
int i;
int j;
for (i = 0; i < 16; i++) {
double angle;
int r;
int g;
int b;
if (i == 0) {
r = g = b = 0;
}
else {
angle = M_PI * (i / 7.0 - colshift * 0.01);
r = (int) (0.08 / 0.30 * cos(angle) * (white - black));
g = (int) (0.08 / 0.59 * cos(angle + M_PI * 2 / 3) * (white - black));
b = (int) (0.08 / 0.11 * cos(angle + M_PI * 4 / 3) * (white - black));
}
for (j = 0; j < 16; j++) {
int y;
y = black + white * j / 15;
Colours_SetRGB(i * 16 + j, y + r, y + g, y + b, colortable_ptr);
}
}
}
void Colours_Adjust(int black, int white, int colintens, int *colortable_ptr)
{
double black_in;
double white_in;
double brightfix;
double colorfix;
int i;
black_in = PALETTE_Y(0, colortable_ptr);
white_in = PALETTE_Y(15, colortable_ptr);
brightfix = (white - black) / (white_in - black_in);
colorfix = brightfix * colintens / 100;
for (i = 0; i < 256; i++) {
double y;
double r;
double g;
double b;
y = PALETTE_Y(i, colortable_ptr);
r = PALETTE_R(i, colortable_ptr) - y;
g = PALETTE_G(i, colortable_ptr) - y;
b = PALETTE_B(i, colortable_ptr) - y;
y = (y - black_in) * brightfix + black;
r = y + r * colorfix;
g = y + g * colorfix;
b = y + b * colorfix;
Colours_SetRGB(i, (int) r, (int) g, (int) b, colortable_ptr);
}
}
void Colours_SetVideoSystem(int mode) {
if (mode == Atari800_TV_NTSC) {
Colours_table = colortable_ntsc;
}
else if (mode == Atari800_TV_PAL) {
Colours_table = colortable_pal;
}
else {
Atari800_Exit(FALSE);
Log_print("Interal error: Invalid Atari800_tv_mode\n");
exit(1);
}
}
void Colours_InitialiseMachine(void)
{
static int saved_tv_mode = Atari800_TV_UNSET;
if (saved_tv_mode == Atari800_TV_UNSET) {
/* Colours_SetVideoSystem was already called in initialisation*/
saved_tv_mode = Atari800_tv_mode;
}
else if (saved_tv_mode != Atari800_tv_mode) {
/* Atari800_tv_mode has changed */
saved_tv_mode = Atari800_tv_mode;
Colours_SetVideoSystem(Atari800_tv_mode);
#if SUPPORTS_PLATFORM_PALETTEUPDATE
PLATFORM_PaletteUpdate();
#endif
}
}
int Colours_Initialise(int *argc, char *argv[])
{
int i;
int j;
#ifndef __PLUS
/* NTSC */
int black_ntsc = 0;
int white_ntsc = 255;
int colintens_ntsc = 100;
int colshift_ntsc = 30;
/* PAL */
int black_pal = 0;
int white_pal = 255;
int colintens_pal = 100;
int colshift_pal = 30;
#else /* __PLUS */
/*XXX FIXME: add pal/ntsc*/
int black = g_Screen.Pal.nBlackLevel;
int white = g_Screen.Pal.nWhiteLevel;
int colintens = g_Screen.Pal.nSaturation;
int colshift = g_Screen.Pal.nColorShift;
#endif /* __PLUS */
int generate_ntsc = FALSE;
int generate_pal = FALSE;
int adjust_ntsc = FALSE;
int adjust_pal = FALSE;
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = FALSE; /* error, argument missing! */
if (strcmp(argv[i], "-blackn") == 0) {
if (i_a) {
black_ntsc = Util_sscandec(argv[++i]);
adjust_ntsc = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-blackp") == 0) {
if (i_a) {
black_pal = Util_sscandec(argv[++i]);
adjust_pal = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-whiten") == 0) {
if (i_a) {
white_ntsc = Util_sscandec(argv[++i]);
adjust_ntsc = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-whitep") == 0) {
if (i_a) {
white_pal = Util_sscandec(argv[++i]);
adjust_pal = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-colorsn") == 0) {
if (i_a) {
colintens_ntsc = Util_sscandec(argv[++i]);
adjust_ntsc = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-colorsp") == 0) {
if (i_a) {
colintens_pal = Util_sscandec(argv[++i]);
adjust_pal = TRUE;
}
else a_m = TRUE;
}
else if (strcmp(argv[i], "-colshiftn") == 0)
if (i_a)
colshift_ntsc = Util_sscandec(argv[++i]);
else a_m = TRUE;
else if (strcmp(argv[i], "-colshiftp") == 0)
if (i_a)
colshift_pal = Util_sscandec(argv[++i]);
else a_m = TRUE;
else if (strcmp(argv[i], "-genpaln") == 0)
generate_ntsc = TRUE;
else if (strcmp(argv[i], "-genpalp") == 0)
generate_pal = TRUE;
else if (strcmp(argv[i], "-paletten") == 0)
if (i_a)
Colours_Read(argv[++i], colortable_ntsc);
else a_m = TRUE;
else if (strcmp(argv[i], "-palettep") == 0)
if (i_a)
Colours_Read(argv[++i], colortable_pal);
else a_m = TRUE;
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-paletten <file> Use external NTSC palette");
Log_print("\t-palettep <file> Use external PAL palette");
Log_print("\t-blackn <0-255> Set NTSC palette black level");
Log_print("\t-blackp <0-255> Set PAL palette black level");
Log_print("\t-whiten <0-255> Set NTSC palette white level");
Log_print("\t-whitep <0-255> Set PAL palette white level");
Log_print("\t-colorsn <num> Set NTSC palette colors saturation");
Log_print("\t-colorsp <num> Set PAL palette colors saturation");
Log_print("\t-genpaln Generate artificial NTSC palette");
Log_print("\t-genpalp Generate artificial PAL palette");
Log_print("\t-colshiftn <num> Set NTSC palette color shift (-genpaln only)");
Log_print("\t-colshiftp <num> Set PAL palette color shift (-genpalp only)");
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return FALSE;
}
}
*argc = j;
if (generate_ntsc) {
Colours_Generate(black_ntsc, white_ntsc, colshift_ntsc, colortable_ntsc);
}
if (generate_pal) {
Colours_Generate(black_pal, white_pal, colshift_pal, colortable_pal);
}
if (adjust_ntsc) {
Colours_Adjust(black_ntsc, white_ntsc, colintens_ntsc, colortable_ntsc);
}
if (adjust_pal) {
Colours_Adjust(black_pal, white_pal, colintens_pal, colortable_pal);
}
Colours_SetVideoSystem(Atari800_tv_mode); /* Atari800_tv_mode is set before calling Colours_Initialise */
return TRUE;
}

View File

@@ -1,19 +0,0 @@
#ifndef COLOURS_H_
#define COLOURS_H_
extern int *Colours_table;
#define Colours_GetR(x) ((UBYTE) (Colours_table[x] >> 16))
#define Colours_GetG(x) ((UBYTE) (Colours_table[x] >> 8))
#define Colours_GetB(x) ((UBYTE) Colours_table[x])
#define Colours_GetY(x) (0.30 * Colours_GetR(x) + 0.59 * Colours_GetG(x) + 0.11 * Colours_GetB(x))
void Colours_SetRGB(int i, int r, int g, int b, int *colortable_ptr);
int Colours_Read(const char *filename, int *colortable_ptr);
void Colours_Generate(int black, int white, int colshift, int *colortable_ptr);
void Colours_Adjust(int black, int white, int colintens, int *colortable_ptr);
void Colours_SetVideoSystem(int mode);
void Colours_InitialiseMachine(void);
int Colours_Initialise(int *argc, char *argv[]);
#endif /* COLOURS_H_ */

View File

@@ -1,311 +0,0 @@
/*
* compfile.c - File I/O and ZLIB compression
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2006 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include "afile.h"
#include "atari.h"
#include "compfile.h"
#include "log.h"
#include "util.h"
/* GZ decompression ------------------------------------------------------ */
/* Opens a GZIP compressed file and decompresses its contents to outfp.
Returns TRUE on success. */
int CompFile_ExtractGZ(const char *infilename, FILE *outfp)
{
#ifndef HAVE_LIBZ
Log_print("This executable cannot decompress ZLIB files");
return FALSE;
#else
/* TODO: replace gz* with low-level light-weight ZLIB functions. */
gzFile gzf = gzopen(infilename, "rb");
void *buf;
int result;
if (gzf == NULL) {
Log_print("ZLIB could not open file %s", infilename);
return FALSE;
}
#define UNCOMPRESS_BUFFER_SIZE 32768
buf = Util_malloc(UNCOMPRESS_BUFFER_SIZE);
do {
result = gzread(gzf, buf, UNCOMPRESS_BUFFER_SIZE);
if (result > 0) {
if ((int) fwrite(buf, 1, result, outfp) != result)
result = -1;
}
} while (result == UNCOMPRESS_BUFFER_SIZE);
free(buf);
gzclose(gzf);
return result >= 0;
#endif /* HAVE_LIBZ */
}
/* DCM decompression ----------------------------------------------------- */
static int fgetw(FILE *fp)
{
int low;
int high;
low = fgetc(fp);
if (low == EOF)
return -1;
high = fgetc(fp);
if (high == EOF)
return -1;
return low + (high << 8);
}
static int fload(void *buf, int size, FILE *fp)
{
return (int) fread(buf, 1, size, fp) == size;
}
static int fsave(void *buf, int size, FILE *fp)
{
return (int) fwrite(buf, 1, size, fp) == size;
}
typedef struct {
FILE *fp;
int sectorcount;
int sectorsize;
int current_sector;
} ATR_Info;
static int write_atr_header(const ATR_Info *pai)
{
int sectorcount;
int sectorsize;
ULONG paras;
struct AFILE_ATR_Header header;
sectorcount = pai->sectorcount;
sectorsize = pai->sectorsize;
paras = (sectorsize != 256 || sectorcount <= 3)
? (sectorcount << 3) /* single density or only boot sectors: sectorcount * 128 / 16 */
: (sectorcount << 4) - 0x18; /* double density with 128-byte boot sectors: (sectorcount * 256 - 3 * 128) / 16 */
memset(&header, 0, sizeof(header));
header.magic1 = AFILE_ATR_MAGIC1;
header.magic2 = AFILE_ATR_MAGIC2;
header.secsizelo = (UBYTE) sectorsize;
header.secsizehi = (UBYTE) (sectorsize >> 8);
header.seccountlo = (UBYTE) paras;
header.seccounthi = (UBYTE) (paras >> 8);
header.hiseccountlo = (UBYTE) (paras >> 16);
header.hiseccounthi = (UBYTE) (paras >> 24);
return fsave(&header, sizeof(header), pai->fp);
}
static int write_atr_sector(ATR_Info *pai, UBYTE *buf)
{
return fsave(buf, pai->current_sector++ <= 3 ? 128 : pai->sectorsize, pai->fp);
}
static int pad_till_sector(ATR_Info *pai, int till_sector)
{
UBYTE zero_buf[256];
memset(zero_buf, 0, sizeof(zero_buf));
while (pai->current_sector < till_sector)
if (!write_atr_sector(pai, zero_buf))
return FALSE;
return TRUE;
}
static int dcm_pass(FILE *infp, ATR_Info *pai)
{
UBYTE sector_buf[256];
memset(sector_buf, 0, sizeof(sector_buf));
for (;;) {
/* sector group */
int sector_no;
int sector_type;
sector_no = fgetw(infp);
sector_type = fgetc(infp);
if (sector_type == 0x45)
return TRUE;
if (sector_no < pai->current_sector) {
Log_print("Error: current sector is %d, next sector group at %d", pai->current_sector, sector_no);
return FALSE;
}
if (!pad_till_sector(pai, sector_no))
return FALSE;
for (;;) {
/* sector */
int i;
switch (sector_type & 0x7f) {
case 0x41:
i = fgetc(infp);
if (i == EOF)
return FALSE;
do {
int b = fgetc(infp);
if (b == EOF)
return FALSE;
sector_buf[i] = (UBYTE) b;
} while (i-- != 0);
break;
case 0x42:
if (!fload(sector_buf + 123, 5, infp))
return FALSE;
memset(sector_buf, sector_buf[123], 123);
break;
case 0x43:
i = 0;
do {
int j;
int c;
j = fgetc(infp);
if (j < i) {
if (j != 0)
return FALSE;
j = 256;
}
if (i < j && !fload(sector_buf + i, j - i, infp))
return FALSE;
if (j >= pai->sectorsize)
break;
i = fgetc(infp);
if (i < j) {
if (i != 0)
return FALSE;
i = 256;
}
c = fgetc(infp);
if (c == EOF)
return FALSE;
memset(sector_buf + j, c, i - j);
} while (i < pai->sectorsize);
break;
case 0x44:
i = fgetc(infp);
if (i == EOF || i >= pai->sectorsize)
return FALSE;
if (!fload(sector_buf + i, pai->sectorsize - i, infp))
return FALSE;
break;
case 0x46:
break;
case 0x47:
if (!fload(sector_buf, pai->sectorsize, infp))
return FALSE;
break;
default:
Log_print("Unrecognized sector coding type 0x%02X", sector_type);
return FALSE;
}
if (!write_atr_sector(pai, sector_buf))
return FALSE;
if (!(sector_type & 0x80))
break; /* goto sector group */
sector_type = fgetc(infp);
if (sector_type == 0x45)
return TRUE;
}
}
}
int CompFile_DCMtoATR(FILE *infp, FILE *outfp)
{
int archive_type;
int archive_flags;
ATR_Info ai;
int pass_flags;
int last_sector;
archive_type = fgetc(infp);
if (archive_type != 0xf9 && archive_type != 0xfa) {
Log_print("This is not a DCM image");
return FALSE;
}
archive_flags = fgetc(infp);
if ((archive_flags & 0x1f) != 1) {
Log_print("Expected pass one first");
if (archive_type == 0xf9)
Log_print("It seems that DCMs of a multi-file archive have been combined in wrong order");
return FALSE;
}
ai.fp = outfp;
ai.current_sector = 1;
switch ((archive_flags >> 5) & 3) {
case 0:
ai.sectorcount = 720;
ai.sectorsize = 128;
break;
case 1:
ai.sectorcount = 720;
ai.sectorsize = 256;
break;
case 2:
ai.sectorcount = 1040;
ai.sectorsize = 128;
break;
default:
Log_print("Unrecognized density");
return FALSE;
}
if (!write_atr_header(&ai))
return FALSE;
pass_flags = archive_flags;
for (;;) {
/* pass */
int block_type;
if (!dcm_pass(infp, &ai))
return FALSE;
if (pass_flags & 0x80)
break;
block_type = fgetc(infp);
if (block_type != archive_type) {
if (block_type == EOF && archive_type == 0xf9) {
Log_print("Multi-part archive error.");
Log_print("To process these files, you must first combine the files into a single file.");
#if defined(WIN32) || defined(DJGPP)
Log_print("COPY /B file1.dcm+file2.dcm+file3.dcm newfile.dcm from the DOS prompt");
#elif defined(linux) || defined(unix)
Log_print("cat file1.dcm file2.dcm file3.dcm >newfile.dcm from the shell");
#endif
}
return FALSE;
}
pass_flags = fgetc(infp);
if ((pass_flags ^ archive_flags) & 0x60) {
Log_print("Density changed inside DCM archive?");
return FALSE;
}
/* TODO: check pass number, this is tricky for >31 */
}
last_sector = ai.current_sector - 1;
if (last_sector <= ai.sectorcount)
return pad_till_sector(&ai, ai.sectorcount + 1);
/* more sectors written: update ATR header */
ai.sectorcount = last_sector;
Util_rewind(outfp);
return write_atr_header(&ai);
}

View File

@@ -1,9 +0,0 @@
#ifndef COMPFILE_H_
#define COMPFILE_H_
#include <stdio.h> /* FILE */
int CompFile_ExtractGZ(const char *infilename, FILE *outfp);
int CompFile_DCMtoATR(FILE *infp, FILE *outfp);
#endif /* COMPFILE_H_ */

View File

@@ -1,481 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Target: standard I/O. */
/* #undef BASIC */
/* Define to use buffered debug output. */
/* #undef BUFFERED_LOG */
/* Define to allow sound clipping. */
/* #undef CLIP_SOUND */
/* Define to 1 if the `closedir' function returns void instead of `int'. */
/* #undef CLOSEDIR_VOID */
/* Define to allow console sound (keyboard clicks). */
#define CONSOLE_SOUND 1
/* Define to activate crash menu after CIM instruction. */
#define CRASH_MENU 1
/* Define to disable bitmap graphics emulation in CURSES target. */
/* #undef CURSES_BASIC */
/* Alternate config filename due to 8+3 fs limit. */
/* #undef DEFAULT_CFG_NAME */
/* Target: Windows with DirectX. */
/* #undef DIRECTX */
/* Define to use back slash as directory separator. */
/* #undef DIR_SEP_BACKSLASH */
/* Target: DOS VGA. */
/* #undef DOSVGA */
/* Define to enable DOS style drives support. */
/* #undef DOS_DRIVES */
/* Define to enable event recording. */
#define EVENT_RECORDING 1
/* Target: Atari Falcon system. */
/* #undef FALCON */
/* Define to use m68k assembler CPU core for Falcon target. */
/* #undef FALCON_CPUASM */
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the `atexit' function. */
#define HAVE_ATEXIT 1
/* Define to 1 if you have the `chmod' function. */
#define HAVE_CHMOD 1
/* Define to 1 if you have the `clock' function. */
#define HAVE_CLOCK 1
/* Define to 1 if you have the <direct.h> header file. */
/* #undef HAVE_DIRECT_H */
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `fdopen' function. */
#define HAVE_FDOPEN 1
/* Define to 1 if you have the `fflush' function. */
#define HAVE_FFLUSH 1
/* Define to 1 if you have the <file.h> header file. */
/* #undef HAVE_FILE_H */
/* Define to 1 if you have the `floor' function. */
#define HAVE_FLOOR 1
/* Define to 1 if you have the `fstat' function. */
#define HAVE_FSTAT 1
/* Define to 1 if you have the `getcwd' function. */
#define HAVE_GETCWD 1
/* Define to 1 if you have the `gethostbyaddr' function. */
#define HAVE_GETHOSTBYADDR 1
/* Define to 1 if you have the `gethostbyname' function. */
#define HAVE_GETHOSTBYNAME 1
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the `inet_ntoa' function. */
#define HAVE_INET_NTOA 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `png' library (-lpng). */
#define HAVE_LIBPNG 1
/* Define to 1 if you have the `z' library (-lz). */
#define HAVE_LIBZ 1
/* Define to 1 if you have the `localtime' function. */
#define HAVE_LOCALTIME 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1
/* Define to 1 if you have the `mkdir' function. */
#define HAVE_MKDIR 1
/* Define to 1 if you have the `mkstemp' function. */
#define HAVE_MKSTEMP 1
/* Define to 1 if you have the `mktemp' function. */
#define HAVE_MKTEMP 1
/* Define to 1 if you have the `modf' function. */
#define HAVE_MODF 1
/* Define to 1 if you have the `nanosleep' function. */
#define HAVE_NANOSLEEP 1
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
/* Define to 1 if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the `opendir' function. */
#define HAVE_OPENDIR 1
/* Define to 1 if you have the `rename' function. */
#define HAVE_RENAME 1
/* Define to 1 if you have the `rewind' function. */
#define HAVE_REWIND 1
/* Define to 1 if you have the `rmdir' function. */
#define HAVE_RMDIR 1
/* Define to 1 if you have the `select' function. */
#define HAVE_SELECT 1
/* Define to 1 if you have the `signal' function. */
#define HAVE_SIGNAL 1
/* Define to 1 if you have the <signal.h> header file. */
#define HAVE_SIGNAL_H 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
/* Define to 1 if you have the `stat' function. */
#define HAVE_STAT 1
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncpy' function. */
#define HAVE_STRNCPY 1
/* Define to 1 if you have the `strrchr' function. */
#define HAVE_STRRCHR 1
/* Define to 1 if you have the `strstr' function. */
#define HAVE_STRSTR 1
/* Define to 1 if you have the `strtol' function. */
#define HAVE_STRTOL 1
/* Define to 1 if you have the `system' function. */
#define HAVE_SYSTEM 1
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/soundcard.h> header file. */
#define HAVE_SYS_SOUNDCARD_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the `time' function. */
#define HAVE_TIME 1
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
/* Define to 1 if you have the `tmpfile' function. */
#define HAVE_TMPFILE 1
/* Define to 1 if you have the `tmpnam' function. */
#define HAVE_TMPNAM 1
/* Define to 1 if you have the `uclock' function. */
/* #undef HAVE_UCLOCK */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <unixio.h> header file. */
/* #undef HAVE_UNIXIO_H */
/* Define to 1 if you have the `unlink' function. */
#define HAVE_UNLINK 1
/* Define to 1 if you have the `usleep' function. */
#define HAVE_USLEEP 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the <winsock2.h> header file. */
/* #undef HAVE_WINSOCK2_H */
/* Define to allow sound interpolation. */
#define INTERPOLATE_SOUND 1
/* Target: Java NestedVM. */
/* #undef JAVANVM */
/* Define to use LINUX joystick. */
/* #undef LINUX_JOYSTICK */
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
/* Define to activate assembler in monitor. */
#define MONITOR_ASSEMBLER 1
/* Define to activate code breakpoints and execution history. */
#define MONITOR_BREAK 1
/* Define to activate user-defined breakpoints. */
/* #undef MONITOR_BREAKPOINTS */
/* Define to activate hints in disassembler. */
#define MONITOR_HINTS 1
/* Define to activate 6502 opcode profiling. */
/* #undef MONITOR_PROFILE */
/* Define to activate readline support in monitor. */
/* #define MONITOR_READLINE 1 */
/* Define to activate TRACE command in monitor. */
/* #undef MONITOR_TRACE */
/* Target: X11 with Motif. */
/* #undef MOTIF */
/* Define to allow color changes inside a scanline. */
#define NEW_CYCLE_EXACT 1
/* Define to use nonlinear POKEY mixing. */
/* #undef NONLINEAR_MIXING */
/* Use NTSC video filter. */
#define NTSC_FILTER 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "pstehlik@sophics.cz"
/* Define to the full name of this package. */
#define PACKAGE_NAME "Atari800"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Atari800 2.1.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "atari800"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.1.0"
/* Define to use page-based attribute array. */
/* #undef PAGED_ATTRIB */
/* Define to emulate the Black Box. */
#define PBI_BB 1
/* Define to emulate the MIO board. */
#define PBI_MIO 1
/* A prototype 80 column card for the 1090 expansion box. */
#define PBI_PROTO80 1
/* Define to emulate the 1400XL/1450XLD. */
#define PBI_XLD 1
/* Target: Sony PlayStation 2. */
/* #undef PS2 */
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to use R: device. */
/* #undef R_IO_DEVICE */
/* Define to use IP network connection with the R: device. */
#define R_NETWORK 1
/* Define to use the host serial port with the R: device. */
/* #undef R_SERIAL */
/* Target: SDL library. */
#define SDL 1
/* Define to the type of arg 1 for `select'. */
#define SELECT_TYPE_ARG1 int
/* Define to the type of args 2, 3 and 4 for `select'. */
#define SELECT_TYPE_ARG234 (fd_set *)
/* Define to the type of arg 5 for `select'. */
#define SELECT_TYPE_ARG5 (struct timeval *)
/* Define to allow serial in/out sound. */
/* #undef SERIO_SOUND */
/* Target: X11 with shared memory extensions. */
/* #undef SHM */
/* Define to activate sound support. */
#define SOUND 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to allow stereo sound. */
#define STEREO_SOUND 1
/* Save additional config file options. */
#define SUPPORTS_PLATFORM_CONFIGSAVE 1
/* Additional config file options. */
#define SUPPORTS_PLATFORM_CONFIGURE 1
/* Update the Palette if it changed. */
#define SUPPORTS_PLATFORM_PALETTEUPDATE 1
/* Platform-specific sleep function. */
/* #undef SUPPORTS_PLATFORM_SLEEP */
/* Reinitialise the sound system. */
#define SUPPORTS_SOUND_REINIT 1
/* Alternate system-wide config file for non-Unix OS. */
/* #undef SYSTEM_WIDE_CFG_FILE */
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
/* #undef TM_IN_SYS_TIME */
/* Target: Curses-compatible library. */
/* #undef USE_CURSES */
/* Define for using cursor/ctrl keys for keyboard joystick. */
/* #undef USE_CURSORBLOCK */
/* Target: Ncurses library. */
/* #undef USE_NCURSES */
/* Define to use very slow computer support (faster -refresh). */
/* #undef VERY_SLOW */
/* Define to allow volume only sound. */
#define VOL_ONLY_SOUND 1
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define if unaligned word access is ok. */
#define WORDS_UNALIGNED_OK 1
/* Target: Standard X11. */
/* #undef X11 */
/* Emulate the XEP80. */
#define XEP80_EMULATION 1
/* Target: X11 with XView. */
/* #undef XVIEW */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#define inline __inline__
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +0,0 @@
#ifndef CPU_H_
#define CPU_H_
#include "config.h"
#ifdef ASAP /* external project, see http://asap.sf.net */
#include "asap_internal.h"
#else
#include "atari.h"
#endif
#define CPU_N_FLAG 0x80
#define CPU_V_FLAG 0x40
#define CPU_B_FLAG 0x10
#define CPU_D_FLAG 0x08
#define CPU_I_FLAG 0x04
#define CPU_Z_FLAG 0x02
#define CPU_C_FLAG 0x01
void CPU_Initialise(void); /* used in the assembler version of cpu.c only */
void CPU_GetStatus(void);
void CPU_PutStatus(void);
void CPU_Reset(void);
void CPU_StateSave(UBYTE SaveVerbose);
void CPU_StateRead(UBYTE SaveVerbose, UBYTE StateVersion);
void CPU_NMI(void);
void CPU_GO(int limit);
#define CPU_GenerateIRQ() (CPU_IRQ = 1)
#ifdef FALCON_CPUASM
extern void CPU_INIT(void);
extern void CPU_GET(void); /* put from CCR, N & Z FLAG into regP */
extern void CPU_PUT(void); /* put from regP into CCR, N & Z FLAG */
#endif
extern UWORD CPU_regPC;
extern UBYTE CPU_regA;
extern UBYTE CPU_regP;
extern UBYTE CPU_regS;
extern UBYTE CPU_regY;
extern UBYTE CPU_regX;
#define CPU_SetN CPU_regP |= CPU_N_FLAG
#define CPU_ClrN CPU_regP &= (~CPU_N_FLAG)
#define CPU_SetV CPU_regP |= CPU_V_FLAG
#define CPU_ClrV CPU_regP &= (~CPU_V_FLAG)
#define CPU_SetB CPU_regP |= CPU_B_FLAG
#define CPU_ClrB CPU_regP &= (~CPU_B_FLAG)
#define CPU_SetD CPU_regP |= CPU_D_FLAG
#define CPU_ClrD CPU_regP &= (~CPU_D_FLAG)
#define CPU_SetI CPU_regP |= CPU_I_FLAG
#define CPU_ClrI CPU_regP &= (~CPU_I_FLAG)
#define CPU_SetZ CPU_regP |= CPU_Z_FLAG
#define CPU_ClrZ CPU_regP &= (~CPU_Z_FLAG)
#define CPU_SetC CPU_regP |= CPU_C_FLAG
#define CPU_ClrC CPU_regP &= (~CPU_C_FLAG)
extern UBYTE CPU_IRQ;
extern void (*CPU_rts_handler)(void);
extern UBYTE CPU_cim_encountered;
#define CPU_REMEMBER_PC_STEPS 64
extern UWORD CPU_remember_PC[CPU_REMEMBER_PC_STEPS];
extern unsigned int CPU_remember_PC_curpos;
extern int CPU_remember_xpos[CPU_REMEMBER_PC_STEPS];
#define CPU_REMEMBER_JMP_STEPS 16
extern UWORD CPU_remember_JMP[CPU_REMEMBER_JMP_STEPS];
extern unsigned int CPU_remember_jmp_curpos;
#ifdef MONITOR_PROFILE
extern int CPU_instruction_count[256];
#endif
#endif /* CPU_H_ */

View File

@@ -1,201 +0,0 @@
/*
* cycle_map.c - part of the ANTIC emulation
*
* Copyright (C) 1995-1998 Perry McFarlane
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include "cycle_map.h"
int CYCLE_MAP_cpu2antic[CYCLE_MAP_SIZE * (17 * 7 + 1)];
int CYCLE_MAP_antic2cpu[CYCLE_MAP_SIZE * (17 * 7 + 1)];
static void try_all_scroll(int md, int use_char_index,
int use_font, int use_bitmap, int *cpu2antic, int *antic2cpu);
static void antic_steal_map(int width, int md, int scroll_offset, int use_char_index,
int use_font, int use_bitmap, char *antic_cycles, int *cpucycles,
int *actualcycles);
static void cpu_cycle_map(char *antic_cycles_orig, int *cpu_cycles, int *actual_cycles);
#undef TEST_CYCLE_MAP
#ifdef TEST_CYCLE_MAP
int main()
{
CYCLE_MAP_Create();
return 0;
};
#endif
static void cpu_cycle_map(char *antic_cycles_orig, int *cpu_cycles, int *actual_cycles)
{
int i;
char antic_cycles[CYCLE_MAP_SIZE];
int antic_xpos;
int cpu_xpos = 0;
for (i = 0; i <= 113; i++)
antic_cycles[i] = antic_cycles_orig[i];
for (i = 114; i < CYCLE_MAP_SIZE; i++)
antic_cycles[i] = '.';
for (i = 0; i < CYCLE_MAP_SIZE; i++)
cpu_cycles[i]=-1;
for (antic_xpos = 0; antic_xpos < CYCLE_MAP_SIZE; antic_xpos++) {
char c = antic_cycles[antic_xpos];
actual_cycles[antic_xpos] = cpu_xpos;
if (c != 'R' && c != 'S' && c != 'F' && c != 'I') {
/*Not a stolen cycle*/
cpu_cycles[cpu_xpos] = antic_xpos;
cpu_xpos++;
}
}
}
void CYCLE_MAP_Create(void)
{
#ifdef TEST_CYCLE_MAP
int i, j;
int *cpu_cycles;
int *actual_cycles;
#endif
char antic_cycles[115];
int k = 0;
antic_steal_map(1, 0, 0, 0, 0, 0, antic_cycles, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* blank line, or mode 8-F following line*/
k = CYCLE_MAP_SIZE * (17 * 0 + 1);
try_all_scroll(0, 1, 1, 0, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode 2,3,4,5 first line */
k = CYCLE_MAP_SIZE * (17 * 1 + 1);
try_all_scroll(0, 0, 1, 0, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode 2,3,4,5 following lines */
k = CYCLE_MAP_SIZE * (17 * 2 + 1);
try_all_scroll(1, 1, 1, 0, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode 6,7 first line */
k = CYCLE_MAP_SIZE * (17 * 3 + 1);
try_all_scroll(1, 0, 1, 0, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode 6,7 following lines */
k = CYCLE_MAP_SIZE * (17 * 4 + 1);
try_all_scroll(0, 0, 0, 1, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode 8,9 first line */
k = CYCLE_MAP_SIZE * (17 * 5 + 1);
try_all_scroll(1, 0, 0, 1, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode A,B,C first line */
k = CYCLE_MAP_SIZE * (17 * 6 + 1);
try_all_scroll(2, 0, 0, 1, &CYCLE_MAP_cpu2antic[k], &CYCLE_MAP_antic2cpu[k]); /* mode D,E,F first line */
#ifdef TEST_CYCLE_MAP
for(j = 0; j < 17 * 7 + 1; j++) {
cpu_cycles = &CYCLE_MAP_cpu2antic[CYCLE_MAP_SIZE * j];
actual_cycles = &CYCLE_MAP_antic2cpu[CYCLE_MAP_SIZE * j];
printf("%3d ", actual_cycles[114]);
for(i = 0; i <= actual_cycles[114] + 6; i++)
printf("%3d, ", cpu_cycles[i]);
printf("\n");
}
#endif
}
static void try_all_scroll(int md, int use_char_index,
int use_font, int use_bitmap, int *cpu2antic, int *antic2cpu)
{
char antic_cycles[115];
int width;
int scroll_offset = 0;
width = 1; /* narrow width without scroll*/
antic_steal_map(width, md, scroll_offset, use_char_index, use_font,
use_bitmap, antic_cycles, &cpu2antic[CYCLE_MAP_SIZE * 0], &antic2cpu[CYCLE_MAP_SIZE * 0]);
width = 2; /* standard without scroll or narrow with scroll */
for (scroll_offset = 0; scroll_offset <= 7; scroll_offset++) {
antic_steal_map(width, md, scroll_offset, use_char_index, use_font,
use_bitmap, antic_cycles, &cpu2antic[CYCLE_MAP_SIZE * (1 + scroll_offset)],
&antic2cpu[CYCLE_MAP_SIZE * (1 + scroll_offset)]);
}
width = 3; /* standard with scroll or wide */
for (scroll_offset = 0; scroll_offset <= 7; scroll_offset++) {
antic_steal_map(width, md, scroll_offset, use_char_index, use_font,
use_bitmap, antic_cycles, &cpu2antic[CYCLE_MAP_SIZE * (9 + scroll_offset)],
&antic2cpu[CYCLE_MAP_SIZE * (9 + scroll_offset)]);
}
}
static void antic_steal_map(int width, int md, int scroll_offset, int use_char_index,
int use_font, int use_bitmap, char *antic_cycles, int *cpu_cycles,
int *actual_cycles)
{
int char_start;
int bitmap_start;
int font_start;
int i;
int dram_pending;
int interval;
int steal;
int max_chars;
/* defaults for wide playfield */
#define CHAR_C 13
#define BITMAP_C (CHAR_C + 2)
#define FONT_C (CHAR_C + 3)
#define END_C (CHAR_C + 95)
#define DMARS_C (CHAR_C + 15)
#define DMARE_C (DMARS_C + 32)
char_start = CHAR_C + scroll_offset;
bitmap_start = BITMAP_C + scroll_offset;
font_start = FONT_C + scroll_offset;
max_chars = 48;
if (width == 2) { /* standard width */
char_start += 8;
bitmap_start += 8;
font_start += 8;
max_chars = 40;
}
else if (width == 1) { /* narrow */
char_start += 16;
bitmap_start += 16;
font_start += 16;
max_chars = 32;
}
interval = (2 << md);
max_chars = (max_chars >> md);
for (i = 0; i <= 113; i++)
antic_cycles[i] = '.';
antic_cycles[114] = '\0';
antic_cycles[0] = 'M';
antic_cycles[1] = antic_cycles[6] = antic_cycles[7] = 'D';
antic_cycles[2] = antic_cycles[3] = antic_cycles[4] = antic_cycles[5] = 'P';
dram_pending = 0;
for (i = 0; i <= 114; i++) {
steal = 0;
if (i <= END_C) {
if (use_char_index && i >= char_start && ((i - char_start) % interval == 0)
&& ((i - char_start) < max_chars * interval)) {
steal = 'I';
}
if (use_font && i >= font_start && ((i - font_start) % interval == 0)
&& ((i - font_start) < max_chars * interval)) {
steal = 'F';
}
if (use_bitmap && i >= bitmap_start && ((i - bitmap_start) % interval == 0)
&& ((i - bitmap_start) < max_chars * interval)) {
steal = 'S';
}
if (i >= DMARS_C && i <= DMARE_C && ((i - DMARS_C) % 4 == 0)) {
dram_pending = 1;
}
}
if (steal !=0 ) {
antic_cycles[i] = steal;
}
else if (dram_pending != 0){
antic_cycles[i] = 'R';
dram_pending = 0;
}
}
cpu_cycle_map(antic_cycles, cpu_cycles, actual_cycles);
}

View File

@@ -1,9 +0,0 @@
#ifndef CYCLE_MAP_H_
#define CYCLE_MAP_H_
#define CYCLE_MAP_SIZE (114 + 9)
extern int CYCLE_MAP_cpu2antic[CYCLE_MAP_SIZE * (17 * 7 + 1)];
extern int CYCLE_MAP_antic2cpu[CYCLE_MAP_SIZE * (17 * 7 + 1)];
void CYCLE_MAP_Create(void);
#endif /* CYCLE_MAP_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
#ifndef DEVICES_H_
#define DEVICES_H_
#include <stdio.h> /* FILENAME_MAX */
#include "atari.h" /* UWORD */
int Devices_Initialise(int *argc, char *argv[]);
int Devices_PatchOS(void);
void Devices_Frame(void);
void Devices_UpdatePatches(void);
UWORD Devices_SkipDeviceName(void);
extern int Devices_enable_h_patch;
extern int Devices_enable_p_patch;
extern int Devices_enable_r_patch;
extern char Devices_atari_h_dir[4][FILENAME_MAX];
extern int Devices_h_read_only;
extern char Devices_h_exe_path[FILENAME_MAX];
extern char Devices_h_current_dir[4][FILENAME_MAX];
int Devices_H_CountOpen(void);
void Devices_H_CloseAll(void);
extern char Devices_print_command[256];
int Devices_SetPrintCommand(const char *command);
#define Devices_ICHIDZ 0x0020
#define Devices_ICDNOZ 0x0021
#define Devices_ICCOMZ 0x0022
#define Devices_ICSTAZ 0x0023
#define Devices_ICBALZ 0x0024
#define Devices_ICBAHZ 0x0025
#define Devices_ICPTLZ 0x0026
#define Devices_ICPTHZ 0x0027
#define Devices_ICBLLZ 0x0028
#define Devices_ICBLHZ 0x0029
#define Devices_ICAX1Z 0x002a
#define Devices_ICAX2Z 0x002b
#define Devices_IOCB0 0x0340
#define Devices_ICHID 0x0000
#define Devices_ICDNO 0x0001
#define Devices_ICCOM 0x0002
#define Devices_ICSTA 0x0003
#define Devices_ICBAL 0x0004
#define Devices_ICBAH 0x0005
#define Devices_ICPTL 0x0006
#define Devices_ICPTH 0x0007
#define Devices_ICBLL 0x0008
#define Devices_ICBLH 0x0009
#define Devices_ICAX1 0x000a
#define Devices_ICAX2 0x000b
#define Devices_ICAX3 0x000c
#define Devices_ICAX4 0x000d
#define Devices_ICAX5 0x000e
#define Devices_ICAX6 0x000f
#define Devices_TABLE_OPEN 0
#define Devices_TABLE_CLOS 2
#define Devices_TABLE_READ 4
#define Devices_TABLE_WRIT 6
#define Devices_TABLE_STAT 8
#define Devices_TABLE_SPEC 10
#define Devices_TABLE_INIT 12
UWORD Devices_UpdateHATABSEntry(char device, UWORD entry_address, UWORD table_address);
void Devices_RemoveHATABSEntry(char device, UWORD entry_address, UWORD table_address);
#endif /* DEVICES_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,569 +0,0 @@
.OPT NO LIST
; emuos.lis - OS bootstrapping code
;
; Copyright (C) 1995-1998 David Firth
; Copyright (C) 2001-2009 Atari800 development team (see DOC/CREDITS)
;
; This file is part of the Atari800 emulator project which emulates
; the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
;
; Atari800 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.
;
; Atari800 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 Atari800; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;
;
; UPDATE EMUOS.LIS
; Start Emulator
; Insert MAC/65 Cartridge
; ENTER #H5:EMUOS.LIS,A
; ASM,,#H0:EMUOS.OBJ
; Exit Emulator
; mkimg -input emuos.obj -image emuos.img -header emuos.h e000 ffff
;
BOOT = $09
RTCLOK = $12
VVBLKI = $0222
VVBLKD = $0224
;
; ============================
; OS Hardware Shadow Registers
; ============================
;
CHART = $02F3
CHBAS = $02F4
CH = $02FC
COLOR4 = $02C8
COLOR0 = $02C4
COLOR1 = $02C5
COLOR2 = $02C6
COLOR3 = $02C7
PCOLR0 = $02C0
PCOLR1 = $02C1
PCOLR2 = $02C2
PCOLR3 = $02C3
SDLSTH = $0231
SDLSTL = $0230
SDMCTL = $022F
STICK0 = $0278
STICK1 = $0279
STICK2 = $027A
STICK3 = $027B
GPRIOR = $026F
SSKCTL = $0232
STRIG0 = $0284
STRIG1 = $0285
STRIG2 = $0286
STRIG3 = $0287
;
DDEVIC = $0300
DUNIT = $0301
DCOMND = $0302
DSTATS = $0303
DBUFLO = $0304
DBUFHI = $0305
DTIMLO = $0306
DTIMHI = $0307
DBYTLO = $0308
DBYTHI = $0309
DAUX1 = $030A
DAUX2 = $030B
;
; ==================
; Hardware Registers
; ==================
;
CHACTL = $D401
CHBASE = $D409
COLBK = $D01A
COLPF0 = $D016
COLPF1 = $D017
COLPF2 = $D018
COLPF3 = $D019
COLPM0 = $D012
COLPM1 = $D013
COLPM2 = $D014
COLPM3 = $D015
CONSOL = $D01F
DLISTH = $D403
DLISTL = $D402
DMACTL = $D400
KBCODE = $D209
IRQEN = $D20E
IRQST = $D20E
NMIRES = $D40F
NMIST = $D40F
PACTL = $D302
PORTA = $D300
PORTB = $D301
PRIOR = $D01B
SKCTL = $D20F
TRIG0 = $D010
TRIG1 = $D011
TRIG2 = $D012
TRIG3 = $D013
VCOUNT = $D40B
;
*= $E000
.BYTE $00,$00,$00,$00,$00,$00,$00,$00
.BYTE $00,$18,$18,$18,$18,$00,$18,$00
.BYTE $00,$66,$66,$66,$00,$00,$00,$00
.BYTE $00,$66,$FF,$66,$66,$FF,$66,$00
.BYTE $18,$3E,$60,$3C,$06,$7C,$18,$00
.BYTE $00,$66,$6C,$18,$30,$66,$46,$00
.BYTE $1C,$36,$1C,$38,$6F,$66,$3B,$00
.BYTE $00,$18,$18,$18,$00,$00,$00,$00
.BYTE $00,$0E,$1C,$18,$18,$1C,$0E,$00
.BYTE $00,$70,$38,$18,$18,$38,$70,$00
.BYTE $00,$66,$3C,$FF,$3C,$66,$00,$00
.BYTE $00,$18,$18,$7E,$18,$18,$00,$00
.BYTE $00,$00,$00,$00,$00,$18,$18,$30
.BYTE $00,$00,$00,$7E,$00,$00,$00,$00
.BYTE $00,$00,$00,$00,$00,$18,$18,$00
.BYTE $00,$06,$0C,$18,$30,$60,$40,$00
.BYTE $00,$3C,$66,$6E,$76,$66,$3C,$00
.BYTE $00,$18,$38,$18,$18,$18,$7E,$00
.BYTE $00,$3C,$66,$0C,$18,$30,$7E,$00
.BYTE $00,$7E,$0C,$18,$0C,$66,$3C,$00
.BYTE $00,$0C,$1C,$3C,$6C,$7E,$0C,$00
.BYTE $00,$7E,$60,$7C,$06,$66,$3C,$00
.BYTE $00,$3C,$60,$7C,$66,$66,$3C,$00
.BYTE $00,$7E,$06,$0C,$18,$30,$30,$00
.BYTE $00,$3C,$66,$3C,$66,$66,$3C,$00
.BYTE $00,$3C,$66,$3E,$06,$0C,$38,$00
.BYTE $00,$00,$18,$18,$00,$18,$18,$00
.BYTE $00,$00,$18,$18,$00,$18,$18,$30
.BYTE $06,$0C,$18,$30,$18,$0C,$06,$00
.BYTE $00,$00,$7E,$00,$00,$7E,$00,$00
.BYTE $60,$30,$18,$0C,$18,$30,$60,$00
.BYTE $00,$3C,$66,$0C,$18,$00,$18,$00
.BYTE $00,$3C,$66,$6E,$6E,$60,$3E,$00
.BYTE $00,$18,$3C,$66,$66,$7E,$66,$00
.BYTE $00,$7C,$66,$7C,$66,$66,$7C,$00
.BYTE $00,$3C,$66,$60,$60,$66,$3C,$00
.BYTE $00,$78,$6C,$66,$66,$6C,$78,$00
.BYTE $00,$7E,$60,$7C,$60,$60,$7E,$00
.BYTE $00,$7E,$60,$7C,$60,$60,$60,$00
.BYTE $00,$3E,$60,$60,$6E,$66,$3E,$00
.BYTE $00,$66,$66,$7E,$66,$66,$66,$00
.BYTE $00,$7E,$18,$18,$18,$18,$7E,$00
.BYTE $00,$06,$06,$06,$06,$66,$3C,$00
.BYTE $00,$66,$6C,$78,$78,$6C,$66,$00
.BYTE $00,$60,$60,$60,$60,$60,$7E,$00
.BYTE $00,$63,$77,$7F,$6B,$63,$63,$00
.BYTE $00,$66,$76,$7E,$7E,$6E,$66,$00
.BYTE $00,$3C,$66,$66,$66,$66,$3C,$00
.BYTE $00,$7C,$66,$66,$7C,$60,$60,$00
.BYTE $00,$3C,$66,$66,$66,$6C,$36,$00
.BYTE $00,$7C,$66,$66,$7C,$6C,$66,$00
.BYTE $00,$3C,$60,$3C,$06,$06,$3C,$00
.BYTE $00,$7E,$18,$18,$18,$18,$18,$00
.BYTE $00,$66,$66,$66,$66,$66,$7E,$00
.BYTE $00,$66,$66,$66,$66,$3C,$18,$00
.BYTE $00,$63,$63,$6B,$7F,$77,$63,$00
.BYTE $00,$66,$66,$3C,$3C,$66,$66,$00
.BYTE $00,$66,$66,$3C,$18,$18,$18,$00
.BYTE $00,$7E,$0C,$18,$30,$60,$7E,$00
.BYTE $00,$1E,$18,$18,$18,$18,$1E,$00
.BYTE $00,$40,$60,$30,$18,$0C,$06,$00
.BYTE $00,$78,$18,$18,$18,$18,$78,$00
.BYTE $00,$08,$1C,$36,$63,$00,$00,$00
.BYTE $00,$00,$00,$00,$00,$00,$FF,$00
.BYTE $00,$36,$7F,$7F,$3E,$1C,$08,$00
.BYTE $18,$18,$18,$1F,$1F,$18,$18,$18
.BYTE $03,$03,$03,$03,$03,$03,$03,$03
.BYTE $18,$18,$18,$F8,$F8,$00,$00,$00
.BYTE $18,$18,$18,$F8,$F8,$18,$18,$18
.BYTE $00,$00,$00,$F8,$F8,$18,$18,$18
.BYTE $03,$07,$0E,$1C,$38,$70,$E0,$C0
.BYTE $C0,$E0,$70,$38,$1C,$0E,$07,$03
.BYTE $01,$03,$07,$0F,$1F,$3F,$7F,$FF
.BYTE $00,$00,$00,$00,$0F,$0F,$0F,$0F
.BYTE $80,$C0,$E0,$F0,$F8,$FC,$FE,$FF
.BYTE $0F,$0F,$0F,$0F,$00,$00,$00,$00
.BYTE $F0,$F0,$F0,$F0,$00,$00,$00,$00
.BYTE $FF,$FF,$00,$00,$00,$00,$00,$00
.BYTE $00,$00,$00,$00,$00,$00,$FF,$FF
.BYTE $00,$00,$00,$00,$F0,$F0,$F0,$F0
.BYTE $00,$1C,$1C,$77,$77,$08,$1C,$00
.BYTE $00,$00,$00,$1F,$1F,$18,$18,$18
.BYTE $00,$00,$00,$FF,$FF,$00,$00,$00
.BYTE $18,$18,$18,$FF,$FF,$18,$18,$18
.BYTE $00,$00,$3C,$7E,$7E,$7E,$3C,$00
.BYTE $00,$00,$00,$00,$FF,$FF,$FF,$FF
.BYTE $C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0
.BYTE $00,$00,$00,$FF,$FF,$18,$18,$18
.BYTE $18,$18,$18,$FF,$FF,$00,$00,$00
.BYTE $F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0
.BYTE $18,$18,$18,$1F,$1F,$00,$00,$00
.BYTE $78,$60,$78,$60,$7E,$18,$1E,$00
.BYTE $00,$18,$3C,$7E,$18,$18,$18,$00
.BYTE $00,$18,$18,$18,$7E,$3C,$18,$00
.BYTE $00,$18,$30,$7E,$30,$18,$00,$00
.BYTE $00,$18,$0C,$7E,$0C,$18,$00,$00
.BYTE $00,$18,$3C,$7E,$7E,$3C,$18,$00
.BYTE $00,$00,$3C,$06,$3E,$66,$3E,$00
.BYTE $00,$60,$60,$7C,$66,$66,$7C,$00
.BYTE $00,$00,$3C,$60,$60,$60,$3C,$00
.BYTE $00,$06,$06,$3E,$66,$66,$3E,$00
.BYTE $00,$00,$3C,$66,$7E,$60,$3C,$00
.BYTE $00,$0E,$18,$3E,$18,$18,$18,$00
.BYTE $00,$00,$3E,$66,$66,$3E,$06,$7C
.BYTE $00,$60,$60,$7C,$66,$66,$66,$00
.BYTE $00,$18,$00,$38,$18,$18,$3C,$00
.BYTE $00,$06,$00,$06,$06,$06,$06,$3C
.BYTE $00,$60,$60,$6C,$78,$6C,$66,$00
.BYTE $00,$38,$18,$18,$18,$18,$3C,$00
.BYTE $00,$00,$66,$7F,$7F,$6B,$63,$00
.BYTE $00,$00,$7C,$66,$66,$66,$66,$00
.BYTE $00,$00,$3C,$66,$66,$66,$3C,$00
.BYTE $00,$00,$7C,$66,$66,$7C,$60,$60
.BYTE $00,$00,$3E,$66,$66,$3E,$06,$06
.BYTE $00,$00,$7C,$66,$60,$60,$60,$00
.BYTE $00,$00,$3E,$60,$3C,$06,$7C,$00
.BYTE $00,$18,$7E,$18,$18,$18,$0E,$00
.BYTE $00,$00,$66,$66,$66,$66,$3E,$00
.BYTE $00,$00,$66,$66,$66,$3C,$18,$00
.BYTE $00,$00,$63,$6B,$7F,$3E,$36,$00
.BYTE $00,$00,$66,$3C,$18,$3C,$66,$00
.BYTE $00,$00,$66,$66,$66,$3E,$0C,$78
.BYTE $00,$00,$7E,$0C,$18,$30,$7E,$00
.BYTE $00,$18,$3C,$7E,$7E,$18,$3C,$00
.BYTE $18,$18,$18,$18,$18,$18,$18,$18
.BYTE $00,$7E,$78,$7C,$6E,$66,$06,$00
.BYTE $08,$18,$38,$78,$38,$18,$08,$00
.BYTE $10,$18,$1C,$1E,$1C,$18,$10,$00
;
DISKIV = $E450
DSKINV = $E453
CIOV = $E456
SIOV = $E459
SETVBV = $E45C
SYSVBV = $E45F
XITVBV = $E462
SIOINV = $E465
SENDEV = $E468
INTINV = $E46B
CIOINV = $E46E
BLKBDV = $E471
WARMSV = $E474
COLDSV = $E477
RBLOKV = $E47A
CSOPIV = $E47D
;
*= DISKIV
JMP HALT
*= DSKINV
JMP HALT
*= CIOV
JMP HALT
*= SIOV
JMP HALT
*= SETVBV
JMP HALT
*= SYSVBV
JMP HALT
*= XITVBV
JMP XITVBL
*= SIOINV
JMP HALT
*= SENDEV
JMP HALT
*= INTINV
JMP HALT
*= CIOINV
JMP HALT
*= BLKBDV
JMP HALT
*= WARMSV
JMP COLDSTART
*= COLDSV
JMP COLDSTART
*= RBLOKV
JMP HALT
*= CSOPIV
JMP HALT
;
*= $F800
COLDSTART
LDX #$FF
TXS
LDA # <SYSVBL
STA VVBLKI
LDA # >SYSVBL
STA VVBLKI+1
LDA # <XITVBL
STA VVBLKD
LDA # >XITVBL
STA VVBLKD+1
LDA # <IRQ
STA $0216
LDA # >IRQ
STA $0217
LDA $0000
BNE RPIIMG ; Run pre-installed image
LDA $0001
BNE RPIIMG ; Run pre-installed image
LDA $BFFC
INC $BFFC
CMP $BFFC
BNE BOOTDISK
; BNE MONTY
JSR CART.INIT
JMP ($BFFA)
CART.INIT
JMP ($BFFE)
;MONTY
; STA $BFFC ; Restore original value to $BFFC
; JMP $0115 ; Run Montezummas Revenge
RPIIMG
JMP ($0000) ; Run pre-installed image
;
BOOTDISK
LDA #$31
STA DDEVIC
LDA #$01
STA DUNIT
LDA #$52
STA DCOMND
LDA #0
STA DBUFLO
LDA #4
STA DBUFHI
LDA #$80
STA DBYTLO
LDA #$00
STA DBYTHI
LDA #1
STA DAUX1
LDA #0
STA DAUX2
JSR SIOV
BMI HALT
LDA $0400
CMP #$FF
BNE BOOTDISK.1
LDA $0401
CMP #$FF
BEQ BINARY.FILE
BOOTDISK.1
STA 0
CLC
LDA $0402
STA DBUFLO
ADC #6
STA 1
LDA $0403
STA DBUFHI
ADC #0
STA 2
LDA $0404
STA 3
LDA $0405
STA 4
?L1
JSR SIOV
BMI HALT
CLC
LDA DBUFLO
ADC #$80
STA DBUFLO
LDA DBUFHI
ADC #0
STA DBUFHI
INC DAUX1
BNE ?L2
INC DAUX2
?L2
DEC 0
BNE ?L1
DEC 5
BPL ?L1
JSR ?L3 ; Run initialisation code
LDA #1
STA BOOT
JSR ?L4 ; Run main program
RTS
?L3
JMP ($01)
?L4
JMP ($03)
;
BINARY.FILE
;
HALT
LDA # <DLIST
STA SDLSTL
STA DLISTL
LDA # >DLIST
STA SDLSTH
STA DLISTH
LDA #$E0
STA CHBASE
STA CHBAS
LDA #$22
STA DMACTL
STA SDMCTL
LDA #$02
STA CHACTL
STA CHART
LDA #$CA
STA COLBK
STA COLOR4
LDA #$94
STA COLPF2
STA COLOR2
LDA #$0A
STA COLPF1
STA COLOR1
;
HALT2
JMP HALT2
DLIST
.BYTE $70,$70,$70
.BYTE $42, <HALTMSG, >HALTMSG
.BYTE $02,$02,$02,$02,$02
.BYTE $02,$02,$02,$02,$02
.BYTE $02,$02,$02,$02,$02
.BYTE $02,$02,$02,$02,$02
.BYTE $02,$02,$02
.BYTE $41, <DLIST, >DLIST
;
HALTMSG
.SBYTE " Atari800/OS Emulation Halted "
.SBYTE " Copyright (c) 1997 David J. Firth "
.SBYTE "(c) 1998-2009 Atari800 Development Team "
.SBYTE " "
.SBYTE " http://atari800.atari.org/ "
.SBYTE " "
.SBYTE "Sorry this program needs a real Atari/OS"
.SBYTE " Visit the Web pages to find out more "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
.SBYTE " "
;
NMI
BIT NMIST
BPL VBI
JMP ($0200)
VBI
PHA
TXA
PHA
TYA
PHA
STA NMIRES
JMP (VVBLKI)
SYSVBL
INC RTCLOK+2
BNE SYSVBL.1
INC RTCLOK+1
BNE SYSVBL.1
INC RTCLOK
SYSVBL.1
LDA SDMCTL
STA DMACTL
LDA SDLSTL
STA DLISTL
LDA SDLSTH
STA DLISTH
LDA COLOR4
STA COLBK
LDA COLOR0
STA COLPF0
LDA COLOR1
STA COLPF1
LDA COLOR2
STA COLPF2
LDA COLOR3
STA COLPF3
LDA PCOLR0
STA COLPM0
LDA PCOLR1
STA COLPM1
LDA PCOLR2
STA COLPM2
LDA PCOLR3
STA COLPM3
LDA CHART
STA CHACTL
LDA CHBAS
STA CHBASE
LDA PORTA
AND #$0F
STA STICK0
LDA PORTA
ASL A
ASL A
ASL A
ASL A
STA STICK1
LDA PORTB
AND #$0F
STA STICK2
LDA PORTB
ASL A
ASL A
ASL A
ASL A
STA STICK3
LDA GPRIOR
STA PRIOR
LDA SSKCTL
STA SKCTL
LDA TRIG0
STA STRIG0
LDA TRIG1
STA STRIG1
LDA TRIG2
STA STRIG2
LDA TRIG3
STA STRIG3
JMP (VVBLKD)
XITVBL
PLA
TAY
PLA
TAX
PLA
IRQ.VECTOR
JMP ($0216)
IRQ
PHA
LDA IRQST ; Get Interrupt Status
AND #$40
BNE IRQ.EXIT
LDA KBCODE
STA CH
IRQ.EXIT
PLA
RTI
;
*= $FFFA
.WORD NMI
*= $FFFC
.WORD COLDSTART
*= $FFFE
.WORD IRQ.VECTOR

View File

@@ -1,197 +0,0 @@
/*
* esc.c - Patch the OS with escape sequences
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "atari.h"
#include "cassette.h"
#include "cpu.h"
#include "devices.h"
#include "esc.h"
#include "log.h"
#include "memory.h"
#include "pia.h"
#include "sio.h"
#include "ui.h"
#include <stdlib.h>
int ESC_enable_sio_patch = TRUE;
/* Now we check address of every escape code, to make sure that the patch
has been set by the emulator and is not a CIM in Atari program.
Also switch() for escape codes has been changed to array of pointers
to functions. This allows adding port-specific patches (e.g. modem device)
using ESC_Add, Devices_UpdateHATABSEntry etc. without modifying
atari.c/devices.c. Unfortunately it can't be done for patches in Atari OS,
because the OS in XL/XE can be disabled.
*/
static UWORD esc_address[256];
static ESC_FunctionType esc_function[256];
void ESC_ClearAll(void)
{
int i;
for (i = 0; i < 256; i++)
esc_function[i] = NULL;
}
void ESC_Add(UWORD address, UBYTE esc_code, ESC_FunctionType function)
{
esc_address[esc_code] = address;
esc_function[esc_code] = function;
MEMORY_dPutByte(address, 0xf2); /* ESC */
MEMORY_dPutByte(address + 1, esc_code); /* ESC CODE */
}
void ESC_AddEscRts(UWORD address, UBYTE esc_code, ESC_FunctionType function)
{
esc_address[esc_code] = address;
esc_function[esc_code] = function;
MEMORY_dPutByte(address, 0xf2); /* ESC */
MEMORY_dPutByte(address + 1, esc_code); /* ESC CODE */
MEMORY_dPutByte(address + 2, 0x60); /* RTS */
}
/* 0xd2 is ESCRTS, which works same as pair of ESC and RTS (I think so...).
So this function does effectively the same as ESC_AddEscRts,
except that it modifies 2, not 3 bytes in Atari memory.
I don't know why it is done that way, so I simply leave it
unchanged (0xf2/0xd2 are used as in previous versions).
*/
void ESC_AddEscRts2(UWORD address, UBYTE esc_code, ESC_FunctionType function)
{
esc_address[esc_code] = address;
esc_function[esc_code] = function;
MEMORY_dPutByte(address, 0xd2); /* ESCRTS */
MEMORY_dPutByte(address + 1, esc_code); /* ESC CODE */
}
void ESC_Remove(UBYTE esc_code)
{
esc_function[esc_code] = NULL;
}
void ESC_Run(UBYTE esc_code)
{
if (esc_address[esc_code] == CPU_regPC - 2 && esc_function[esc_code] != NULL) {
esc_function[esc_code]();
return;
}
#ifdef CRASH_MENU
CPU_regPC -= 2;
UI_crash_address = CPU_regPC;
UI_crash_afterCIM = CPU_regPC + 2;
UI_crash_code = MEMORY_dGetByte(UI_crash_address);
UI_Run();
#else /* CRASH_MENU */
CPU_cim_encountered = 1;
Log_print("Invalid ESC code %02x at address %04x", esc_code, CPU_regPC - 2);
#ifndef __PLUS
if (!Atari800_Exit(TRUE))
exit(0);
#else /* __PLUS */
Atari800_Exit(TRUE);
#endif /* __PLUS */
#endif /* CRASH_MENU */
}
void ESC_PatchOS(void)
{
int patched = Devices_PatchOS();
if (ESC_enable_sio_patch) {
UWORD addr_l;
UWORD addr_s;
UBYTE check_s_0;
UBYTE check_s_1;
/* patch Open() of C: so we know when a leader is processed */
switch (Atari800_machine_type) {
case Atari800_MACHINE_OSA:
case Atari800_MACHINE_OSB:
addr_l = 0xef74;
addr_s = 0xefbc;
check_s_0 = 0xa0;
check_s_1 = 0x80;
break;
case Atari800_MACHINE_XLXE:
addr_l = 0xfd13;
addr_s = 0xfd60;
check_s_0 = 0xa9;
check_s_1 = 0x03;
break;
default:
return;
}
/* don't hurt non-standard OSes that may not support cassette at all */
if (MEMORY_dGetByte(addr_l) == 0xa9 && MEMORY_dGetByte(addr_l + 1) == 0x03
&& MEMORY_dGetByte(addr_l + 2) == 0x8d && MEMORY_dGetByte(addr_l + 3) == 0x2a
&& MEMORY_dGetByte(addr_l + 4) == 0x02
&& MEMORY_dGetByte(addr_s) == check_s_0
&& MEMORY_dGetByte(addr_s + 1) == check_s_1
&& MEMORY_dGetByte(addr_s + 2) == 0x20 && MEMORY_dGetByte(addr_s + 3) == 0x5c
&& MEMORY_dGetByte(addr_s + 4) == 0xe4) {
ESC_Add(addr_l, ESC_COPENLOAD, CASSETTE_LeaderLoad);
ESC_Add(addr_s, ESC_COPENSAVE, CASSETTE_LeaderSave);
}
ESC_AddEscRts(0xe459, ESC_SIOV, SIO_Handler);
patched = TRUE;
}
else {
ESC_Remove(ESC_COPENLOAD);
ESC_Remove(ESC_COPENSAVE);
ESC_Remove(ESC_SIOV);
};
if (patched && Atari800_machine_type == Atari800_MACHINE_XLXE) {
/* Disable Checksum Test */
MEMORY_dPutByte(0xc314, 0x8e);
MEMORY_dPutByte(0xc315, 0xff);
MEMORY_dPutByte(0xc319, 0x8e);
MEMORY_dPutByte(0xc31a, 0xff);
}
}
void ESC_UpdatePatches(void)
{
switch (Atari800_machine_type) {
case Atari800_MACHINE_OSA:
case Atari800_MACHINE_OSB:
/* Restore unpatched OS */
MEMORY_dCopyToMem(MEMORY_os, 0xd800, 0x2800);
/* Set patches */
ESC_PatchOS();
Devices_UpdatePatches();
break;
case Atari800_MACHINE_XLXE:
/* Don't patch if OS disabled */
if ((PIA_PORTB & 1) == 0)
break;
/* Restore unpatched OS */
MEMORY_dCopyToMem(MEMORY_os, 0xc000, 0x1000);
MEMORY_dCopyToMem(MEMORY_os + 0x1800, 0xd800, 0x2800);
/* Set patches */
ESC_PatchOS();
Devices_UpdatePatches();
break;
default:
break;
}
}

View File

@@ -1,96 +0,0 @@
#ifndef ESC_H_
#define ESC_H_
/* TRUE to enable patched (fast) Serial I/O. */
extern int ESC_enable_sio_patch;
/* Escape codes used to mark places in 6502 code that must
be handled specially by the emulator. An escape sequence
is an illegal 6502 opcode 0xF2 or 0xD2 followed
by one of these escape codes: */
enum ESC_t {
/* SIO patch. */
ESC_SIOV,
/* stdio-based handlers for the BASIC version
and handlers for Atari Basic loader. */
ESC_EHOPEN,
ESC_EHCLOS,
ESC_EHREAD,
ESC_EHWRIT,
ESC_EHSTAT,
ESC_EHSPEC,
ESC_KHOPEN,
ESC_KHCLOS,
ESC_KHREAD,
ESC_KHWRIT,
ESC_KHSTAT,
ESC_KHSPEC,
/* Atari executable loader. */
ESC_BINLOADER_CONT,
/* Cassette emulation. */
ESC_COPENLOAD = 0xa8,
ESC_COPENSAVE = 0xa9,
/* Printer. */
ESC_PHOPEN = 0xb0,
ESC_PHCLOS = 0xb1,
ESC_PHREAD = 0xb2,
ESC_PHWRIT = 0xb3,
ESC_PHSTAT = 0xb4,
ESC_PHSPEC = 0xb5,
ESC_PHINIT = 0xb6,
#ifdef R_IO_DEVICE
/* R: device. */
ESC_ROPEN = 0xd0,
ESC_RCLOS = 0xd1,
ESC_RREAD = 0xd2,
ESC_RWRIT = 0xd3,
ESC_RSTAT = 0xd4,
ESC_RSPEC = 0xd5,
ESC_RINIT = 0xd6,
#endif
/* H: device. */
ESC_HHOPEN = 0xc0,
ESC_HHCLOS = 0xc1,
ESC_HHREAD = 0xc2,
ESC_HHWRIT = 0xc3,
ESC_HHSTAT = 0xc4,
ESC_HHSPEC = 0xc5,
ESC_HHINIT = 0xc6
};
/* A function called to handle an escape sequence. */
typedef void (*ESC_FunctionType)(void);
/* Puts an escape sequence at the specified address. */
void ESC_Add(UWORD address, UBYTE esc_code, ESC_FunctionType function);
/* Puts an escape sequence followed by the RTS instruction. */
void ESC_AddEscRts(UWORD address, UBYTE esc_code, ESC_FunctionType function);
/* Puts an escape sequence with an integrated RTS. */
void ESC_AddEscRts2(UWORD address, UBYTE esc_code, ESC_FunctionType function);
/* Unregisters an escape sequence. You must cleanup the Atari memory yourself. */
void ESC_Remove(UBYTE esc_code);
/* Handles an escape sequence. */
void ESC_Run(UBYTE esc_code);
/* Installs SIO patch and disables ROM checksum test. */
void ESC_PatchOS(void);
/* Unregisters all escape sequences */
void ESC_ClearAll(void);
/* Reinitializes patches after enable_*_patch change. */
void ESC_UpdatePatches(void);
#endif /* ESC_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,139 +0,0 @@
#ifndef GTIA_H_
#define GTIA_H_
#include "atari.h"
#include "screen.h"
#define GTIA_OFFSET_HPOSP0 0x00
#define GTIA_OFFSET_M0PF 0x00
#define GTIA_OFFSET_HPOSP1 0x01
#define GTIA_OFFSET_M1PF 0x01
#define GTIA_OFFSET_HPOSP2 0x02
#define GTIA_OFFSET_M2PF 0x02
#define GTIA_OFFSET_HPOSP3 0x03
#define GTIA_OFFSET_M3PF 0x03
#define GTIA_OFFSET_HPOSM0 0x04
#define GTIA_OFFSET_P0PF 0x04
#define GTIA_OFFSET_HPOSM1 0x05
#define GTIA_OFFSET_P1PF 0x05
#define GTIA_OFFSET_HPOSM2 0x06
#define GTIA_OFFSET_P2PF 0x06
#define GTIA_OFFSET_HPOSM3 0x07
#define GTIA_OFFSET_P3PF 0x07
#define GTIA_OFFSET_SIZEP0 0x08
#define GTIA_OFFSET_M0PL 0x08
#define GTIA_OFFSET_SIZEP1 0x09
#define GTIA_OFFSET_M1PL 0x09
#define GTIA_OFFSET_SIZEP2 0x0a
#define GTIA_OFFSET_M2PL 0x0a
#define GTIA_OFFSET_SIZEP3 0x0b
#define GTIA_OFFSET_M3PL 0x0b
#define GTIA_OFFSET_SIZEM 0x0c
#define GTIA_OFFSET_P0PL 0x0c
#define GTIA_OFFSET_GRAFP0 0x0d
#define GTIA_OFFSET_P1PL 0x0d
#define GTIA_OFFSET_GRAFP1 0x0e
#define GTIA_OFFSET_P2PL 0x0e
#define GTIA_OFFSET_GRAFP2 0x0f
#define GTIA_OFFSET_P3PL 0x0f
#define GTIA_OFFSET_GRAFP3 0x10
#define GTIA_OFFSET_TRIG0 0x10
#define GTIA_OFFSET_GRAFM 0x11
#define GTIA_OFFSET_TRIG1 0x11
#define GTIA_OFFSET_COLPM0 0x12
#define GTIA_OFFSET_TRIG2 0x12
#define GTIA_OFFSET_COLPM1 0x13
#define GTIA_OFFSET_TRIG3 0x13
#define GTIA_OFFSET_COLPM2 0x14
#define GTIA_OFFSET_PAL 0x14
#define GTIA_OFFSET_COLPM3 0x15
#define GTIA_OFFSET_COLPF0 0x16
#define GTIA_OFFSET_COLPF1 0x17
#define GTIA_OFFSET_COLPF2 0x18
#define GTIA_OFFSET_COLPF3 0x19
#define GTIA_OFFSET_COLBK 0x1a
#define GTIA_OFFSET_PRIOR 0x1b
#define GTIA_OFFSET_VDELAY 0x1c
#define GTIA_OFFSET_GRACTL 0x1d
#define GTIA_OFFSET_HITCLR 0x1e
#define GTIA_OFFSET_CONSOL 0x1f
extern UBYTE GTIA_GRAFM;
extern UBYTE GTIA_GRAFP0;
extern UBYTE GTIA_GRAFP1;
extern UBYTE GTIA_GRAFP2;
extern UBYTE GTIA_GRAFP3;
extern UBYTE GTIA_HPOSP0;
extern UBYTE GTIA_HPOSP1;
extern UBYTE GTIA_HPOSP2;
extern UBYTE GTIA_HPOSP3;
extern UBYTE GTIA_HPOSM0;
extern UBYTE GTIA_HPOSM1;
extern UBYTE GTIA_HPOSM2;
extern UBYTE GTIA_HPOSM3;
extern UBYTE GTIA_SIZEP0;
extern UBYTE GTIA_SIZEP1;
extern UBYTE GTIA_SIZEP2;
extern UBYTE GTIA_SIZEP3;
extern UBYTE GTIA_SIZEM;
extern UBYTE GTIA_COLPM0;
extern UBYTE GTIA_COLPM1;
extern UBYTE GTIA_COLPM2;
extern UBYTE GTIA_COLPM3;
extern UBYTE GTIA_COLPF0;
extern UBYTE GTIA_COLPF1;
extern UBYTE GTIA_COLPF2;
extern UBYTE GTIA_COLPF3;
extern UBYTE GTIA_COLBK;
extern UBYTE GTIA_GRACTL;
extern UBYTE GTIA_M0PL;
extern UBYTE GTIA_M1PL;
extern UBYTE GTIA_M2PL;
extern UBYTE GTIA_M3PL;
extern UBYTE GTIA_P0PL;
extern UBYTE GTIA_P1PL;
extern UBYTE GTIA_P2PL;
extern UBYTE GTIA_P3PL;
extern UBYTE GTIA_PRIOR;
extern UBYTE GTIA_VDELAY;
#ifdef USE_COLOUR_TRANSLATION_TABLE
extern UWORD GTIA_colour_translation_table[256];
#define GTIA_COLOUR_BLACK GTIA_colour_translation_table[0]
#define GTIA_COLOUR_TO_WORD(dest,src) dest = GTIA_colour_translation_table[src];
#else
#define GTIA_COLOUR_BLACK 0
#define GTIA_COLOUR_TO_WORD(dest,src) dest = (((UWORD) (src)) << 8) | (src);
#endif /* USE_COLOUR_TRANSLATION_TABLE */
extern UBYTE GTIA_pm_scanline[Screen_WIDTH / 2 + 8]; /* there's a byte for every *pair* of pixels */
extern int GTIA_pm_dirty;
extern UBYTE GTIA_collisions_mask_missile_playfield;
extern UBYTE GTIA_collisions_mask_player_playfield;
extern UBYTE GTIA_collisions_mask_missile_player;
extern UBYTE GTIA_collisions_mask_player_player;
extern UBYTE GTIA_TRIG[4];
extern UBYTE GTIA_TRIG_latch[4];
extern int GTIA_consol_index;
extern UBYTE GTIA_consol_table[3];
extern int GTIA_speaker;
int GTIA_Initialise(int *argc, char *argv[]);
void GTIA_Frame(void);
void GTIA_NewPmScanline(void);
UBYTE GTIA_GetByte(UWORD addr);
void GTIA_PutByte(UWORD addr, UBYTE byte);
void GTIA_StateSave(void);
void GTIA_StateRead(void);
#ifdef NEW_CYCLE_EXACT
void GTIA_UpdatePmplColls(void);
#endif
#endif /* GTIA_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
#ifndef INPUT_H_
#define INPUT_H_
/* Keyboard AKEY_* are in akey.h */
/* INPUT_key_consol masks */
/* Note: INPUT_key_consol should be INPUT_CONSOL_NONE if no consol key is pressed.
When a consol key is pressed, corresponding bit should be cleared.
*/
#define INPUT_CONSOL_NONE 0x07
#define INPUT_CONSOL_START 0x01
#define INPUT_CONSOL_SELECT 0x02
#define INPUT_CONSOL_OPTION 0x04
extern int INPUT_key_code; /* regular Atari key code */
extern int INPUT_key_shift; /* Shift key pressed */
extern int INPUT_key_consol; /* Start, Select and Option keys */
/* Joysticks ----------------------------------------------------------- */
/* joystick position */
#define INPUT_STICK_LL 0x09
#define INPUT_STICK_BACK 0x0d
#define INPUT_STICK_LR 0x05
#define INPUT_STICK_LEFT 0x0b
#define INPUT_STICK_CENTRE 0x0f
#define INPUT_STICK_RIGHT 0x07
#define INPUT_STICK_UL 0x0a
#define INPUT_STICK_FORWARD 0x0e
#define INPUT_STICK_UR 0x06
/* joy_autofire values */
#define INPUT_AUTOFIRE_OFF 0
#define INPUT_AUTOFIRE_FIRE 1 /* Fire dependent */
#define INPUT_AUTOFIRE_CONT 2 /* Continuous */
extern int INPUT_joy_autofire[4]; /* autofire mode for each Atari port */
extern int INPUT_joy_block_opposite_directions; /* can't move joystick left
and right simultaneously */
extern int INPUT_joy_multijoy; /* emulate MultiJoy4 interface */
/* 5200 joysticks values */
extern int INPUT_joy_5200_min;
extern int INPUT_joy_5200_center;
extern int INPUT_joy_5200_max;
/* Mouse --------------------------------------------------------------- */
/* INPUT_mouse_mode values */
#define INPUT_MOUSE_OFF 0
#define INPUT_MOUSE_PAD 1 /* Paddles */
#define INPUT_MOUSE_TOUCH 2 /* Atari touch tablet */
#define INPUT_MOUSE_KOALA 3 /* Koala pad */
#define INPUT_MOUSE_PEN 4 /* Light pen */
#define INPUT_MOUSE_GUN 5 /* Light gun */
#define INPUT_MOUSE_AMIGA 6 /* Amiga mouse */
#define INPUT_MOUSE_ST 7 /* Atari ST mouse */
#define INPUT_MOUSE_TRAK 8 /* Atari CX22 Trak-Ball */
#define INPUT_MOUSE_JOY 9 /* Joystick */
extern int INPUT_mouse_mode; /* device emulated with mouse */
extern int INPUT_mouse_port; /* Atari port, to which the emulated device is attached */
extern int INPUT_mouse_delta_x; /* x motion since last frame */
extern int INPUT_mouse_delta_y; /* y motion since last frame */
extern int INPUT_mouse_buttons; /* buttons pressed (b0: left, b1: right, b2: middle */
extern int INPUT_mouse_speed; /* how fast the mouse pointer moves */
extern int INPUT_mouse_pot_min; /* min. value of POKEY's POT register */
extern int INPUT_mouse_pot_max; /* max. value of POKEY's POT register */
extern int INPUT_mouse_pen_ofs_h; /* light pen/gun horizontal offset (for calibration) */
extern int INPUT_mouse_pen_ofs_v; /* light pen/gun vertical offset (for calibration) */
extern int INPUT_mouse_joy_inertia; /* how long the mouse pointer can move (time in Atari frames)
after a fast motion of mouse */
extern int INPUT_direct_mouse; /* When true, convert the mouse pointer
position directly into POKEY POT values */
extern int INPUT_cx85; /* emulate CX85 numeric keypad */
/* Functions ----------------------------------------------------------- */
int INPUT_Initialise(int *argc, char *argv[]);
void INPUT_Exit(void);
void INPUT_Frame(void);
void INPUT_Scanline(void);
void INPUT_SelectMultiJoy(int no);
void INPUT_CenterMousePointer(void);
void INPUT_DrawMousePointer(void);
int INPUT_Recording(void);
int INPUT_Playingback(void);
void INPUT_RecordInt(int i);
int INPUT_PlaybackInt(void);
#endif /* INPUT_H_ */

View File

@@ -1,238 +0,0 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# 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.
#
# 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}"
tranformbasename=""
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

View File

@@ -1,90 +0,0 @@
/*
* log.c - A logging facility for debugging
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#ifdef ANDROID
#include <android/log.h>
#endif
#include "log.h"
#ifdef MACOSX
# define PRINT(a) ControlManagerMessagePrint(a)
#elif defined(ANDROID)
# define PRINT(a) __android_log_print(ANDROID_LOG_INFO, "atari800", a);
#else
# define PRINT(a) printf("%s", a)
#endif
#ifdef BUFFERED_LOG
char Log_buffer[Log_BUFFER_SIZE] = "";
#endif
void Log_print(char *format, ...)
{
va_list args;
char buffer[8192];
#ifdef BUFFERED_LOG
int buflen;
#endif
va_start(args, format);
#ifdef HAVE_VSNPRINTF
vsnprintf(buffer, sizeof(buffer) - 2 /* -2 for the strcat() */, format, args);
#else
vsprintf(buffer, format, args);
#endif
va_end(args);
#ifdef __PLUS
strcat(buffer, "\r\n");
#else
strcat(buffer, "\n");
#endif
#ifdef BUFFERED_LOG
buflen = strlen(buffer);
if ((strlen(Log_buffer) + strlen(buffer) + 1) > Log_BUFFER_SIZE)
*Log_buffer = 0;
strcat(Log_buffer, buffer);
#else
PRINT(buffer);
#endif
}
void Log_flushlog(void)
{
#ifdef BUFFERED_LOG
if (*Log_buffer) {
PRINT(Log_buffer);
*Log_buffer = 0;
}
#endif
}

View File

@@ -1,10 +0,0 @@
#ifndef LOG_H_
#define LOG_H_
#define Log_BUFFER_SIZE 8192
extern char Log_buffer[Log_BUFFER_SIZE];
void Log_print(char *format, ...);
void Log_flushlog(void);
#endif /* LOG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +0,0 @@
#ifndef MEMORY_H_
#define MEMORY_H_
#include "config.h"
#include <string.h> /* memcpy, memset */
#include "atari.h"
#define MEMORY_dGetByte(x) (MEMORY_mem[x])
#define MEMORY_dPutByte(x, y) (MEMORY_mem[x] = y)
#ifndef WORDS_BIGENDIAN
#ifdef WORDS_UNALIGNED_OK
#define MEMORY_dGetWord(x) UNALIGNED_GET_WORD(&MEMORY_mem[x], memory_read_word_stat)
#define MEMORY_dPutWord(x, y) UNALIGNED_PUT_WORD(&MEMORY_mem[x], (y), memory_write_word_stat)
#define MEMORY_dGetWordAligned(x) UNALIGNED_GET_WORD(&MEMORY_mem[x], memory_read_aligned_word_stat)
#define MEMORY_dPutWordAligned(x, y) UNALIGNED_PUT_WORD(&MEMORY_mem[x], (y), memory_write_aligned_word_stat)
#else /* WORDS_UNALIGNED_OK */
#define MEMORY_dGetWord(x) (MEMORY_mem[x] + (MEMORY_mem[(x) + 1] << 8))
#define MEMORY_dPutWord(x, y) (MEMORY_mem[x] = (UBYTE) (y), MEMORY_mem[(x) + 1] = (UBYTE) ((y) >> 8))
/* faster versions of MEMORY_jdGetWord and MEMORY_dPutWord for even addresses */
/* TODO: guarantee that memory is UWORD-aligned and use UWORD access */
#define MEMORY_dGetWordAligned(x) MEMORY_dGetWord(x)
#define MEMORY_dPutWordAligned(x, y) MEMORY_dPutWord(x, y)
#endif /* WORDS_UNALIGNED_OK */
#else /* WORDS_BIGENDIAN */
/* can't do any word optimizations for big endian machines */
#define MEMORY_dGetWord(x) (MEMORY_mem[x] + (MEMORY_mem[(x) + 1] << 8))
#define MEMORY_dPutWord(x, y) (MEMORY_mem[x] = (UBYTE) (y), MEMORY_mem[(x) + 1] = (UBYTE) ((y) >> 8))
#define MEMORY_dGetWordAligned(x) MEMORY_dGetWord(x)
#define MEMORY_dPutWordAligned(x, y) MEMORY_dPutWord(x, y)
#endif /* WORDS_BIGENDIAN */
#define MEMORY_dCopyFromMem(from, to, size) memcpy(to, MEMORY_mem + (from), size)
#define MEMORY_dCopyToMem(from, to, size) memcpy(MEMORY_mem + (to), from, size)
#define MEMORY_dFillMem(addr1, value, length) memset(MEMORY_mem + (addr1), value, length)
extern UBYTE MEMORY_mem[65536 + 2];
/* RAM size in kilobytes.
Valid values for Atari800_MACHINE_OSA and Atari800_MACHINE_OSB are: 16, 48, 52.
Valid values for Atari800_MACHINE_XLXE are: 16, 64, 128, 192, RAM_320_RAMBO,
RAM_320_COMPY_SHOP, 576, 1088.
The only valid value for Atari800_MACHINE_5200 is 16. */
#define MEMORY_RAM_320_RAMBO 320
#define MEMORY_RAM_320_COMPY_SHOP 321
extern int MEMORY_ram_size;
#define MEMORY_RAM 0
#define MEMORY_ROM 1
#define MEMORY_HARDWARE 2
#ifndef PAGED_ATTRIB
extern UBYTE MEMORY_attrib[65536];
#define MEMORY_GetByte(addr) (MEMORY_attrib[addr] == MEMORY_HARDWARE ? MEMORY_HwGetByte(addr) : MEMORY_mem[addr])
#define MEMORY_PutByte(addr, byte) do { if (MEMORY_attrib[addr] == MEMORY_RAM) MEMORY_mem[addr] = byte; else if (MEMORY_attrib[addr] == MEMORY_HARDWARE) MEMORY_HwPutByte(addr, byte); } while (0)
#define MEMORY_SetRAM(addr1, addr2) memset(MEMORY_attrib + (addr1), MEMORY_RAM, (addr2) - (addr1) + 1)
#define MEMORY_SetROM(addr1, addr2) memset(MEMORY_attrib + (addr1), MEMORY_ROM, (addr2) - (addr1) + 1)
#define MEMORY_SetHARDWARE(addr1, addr2) memset(MEMORY_attrib + (addr1), MEMORY_HARDWARE, (addr2) - (addr1) + 1)
#else /* PAGED_ATTRIB */
typedef UBYTE (*MEMORY_rdfunc)(UWORD addr);
typedef void (*MEMORY_wrfunc)(UWORD addr, UBYTE value);
extern MEMORY_rdfunc MEMORY_readmap[256];
extern MEMORY_wrfunc MEMORY_writemap[256];
void MEMORY_ROM_PutByte(UWORD addr, UBYTE byte);
#define MEMORY_GetByte(addr) (MEMORY_readmap[(addr) >> 8] ? (*MEMORY_readmap[(addr) >> 8])(addr) : MEMORY_mem[addr])
#define MEMORY_PutByte(addr,byte) (MEMORY_writemap[(addr) >> 8] ? ((*MEMORY_writemap[(addr) >> 8])(addr, byte), 0) : (MEMORY_mem[addr] = byte))
#define MEMORY_SetRAM(addr1, addr2) do { \
int i; \
for (i = (addr1) >> 8; i <= (addr2) >> 8; i++) { \
MEMORY_readmap[i] = NULL; \
MEMORY_writemap[i] = NULL; \
} \
} while (0)
#define MEMORY_SetROM(addr1, addr2) do { \
int i; \
for (i = (addr1) >> 8; i <= (addr2) >> 8; i++) { \
MEMORY_readmap[i] = NULL; \
MEMORY_writemap[i] = MEMORY_ROM_PutByte; \
} \
} while (0)
#endif /* PAGED_ATTRIB */
extern UBYTE MEMORY_basic[8192];
extern UBYTE MEMORY_os[16384];
extern int MEMORY_xe_bank;
extern int MEMORY_selftest_enabled;
extern int MEMORY_have_basic;
extern int MEMORY_cartA0BF_enabled;
void MEMORY_InitialiseMachine(void);
void MEMORY_StateSave(UBYTE SaveVerbose);
void MEMORY_StateRead(UBYTE SaveVerbose, UBYTE StateVersion);
void MEMORY_CopyFromMem(UWORD from, UBYTE *to, int size);
void MEMORY_CopyToMem(const UBYTE *from, UWORD to, int size);
void MEMORY_HandlePORTB(UBYTE byte, UBYTE oldval);
void MEMORY_Cart809fDisable(void);
void MEMORY_Cart809fEnable(void);
void MEMORY_CartA0bfDisable(void);
void MEMORY_CartA0bfEnable(void);
#define MEMORY_CopyROM(addr1, addr2, src) memcpy(MEMORY_mem + (addr1), src, (addr2) - (addr1) + 1)
void MEMORY_GetCharset(UBYTE *cs);
/* Mosaic and Axlon 400/800 RAM extensions */
extern int MEMORY_mosaic_maxbank;
extern int MEMORY_mosaic_enabled;
extern int MEMORY_axlon_enabled;
extern int MEMORY_axlon_0f_mirror;
extern int MEMORY_axlon_bankmask;
#ifndef PAGED_MEM
/* Reads a byte from the specified special address (not RAM or ROM). */
UBYTE MEMORY_HwGetByte(UWORD addr);
/* Stores a byte at the specified special address (not RAM or ROM). */
void MEMORY_HwPutByte(UWORD addr, UBYTE byte);
#endif /* PAGED_MEM */
#endif /* MEMORY_H_ */

View File

@@ -1,208 +0,0 @@
/*
* mkimg.c - Make an image or .h file from a binary
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Usage: mkimg -input filename
* -image filename
* -header filename
* hexaddr1
* hexaddr2
*
* Loads the input file into a 64K area of memory. The
* input file is in standard Atari Binary load format.
* The memory is initially filled with zeros. After the
* memory has been loaded the program creates either an
* image file or a standard C header file that contains
* the memory starting with hexaddr1 at going up to,
* but not including, hexaddr2.
*/
#include <stdio.h>
#include <string.h>
typedef enum {
Expect_Header1,
Expect_Header2,
Expect_StartLo,
Expect_StartHi,
Expect_FinishLo,
Expect_FinishHi,
Expect_Data
} State;
int main(int argc, char *argv[])
{
unsigned char image[65536];
char *in_filename = NULL;
char *image_filename = NULL;
char *header_filename = NULL;
int error = 0;
int start_addr = 0;
int finish_addr = 0;
int addr1 = -1;
int addr2 = -1;
int addr;
FILE *f;
int i;
State state = Expect_Header1;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-input") == 0)
in_filename = argv[++i];
else if (strcmp(argv[i], "-image") == 0)
image_filename = argv[++i];
else if (strcmp(argv[i], "-header") == 0)
header_filename = argv[++i];
else if (addr1 == -1)
sscanf(argv[i], "%x", &addr1);
else if (addr2 == -1)
sscanf(argv[i], "%x", &addr2);
else
error = 1;
}
if (!in_filename || (!image_filename && !header_filename) ||
error || (addr1 == -1) || (addr2 == -1)) {
printf("Usage: %s -input in_fname {-image image_fname|-header header_fname} hexaddr1 hexaddr2\n",
argv[0]);
return 0;
}
memset(image, 0, 65536);
f = fopen(in_filename, "rb");
if (!f) {
perror(in_filename);
return 1;
}
while (1) {
unsigned char byte;
if (fread(&byte, 1, 1, f) != 1)
break;
switch (state) {
case Expect_Header1:
if (byte == 0xff)
state = Expect_Header2;
else
printf("Error: Expecting Header1\n");
break;
case Expect_Header2:
if (byte == 0xff)
state = Expect_StartLo;
else
printf("Error: Expecting Header2\n");
break;
case Expect_StartLo:
start_addr = (start_addr & 0xff00) | byte;
state = Expect_StartHi;
break;
case Expect_StartHi:
start_addr = (start_addr & 0x00ff) | (byte << 8);
state = Expect_FinishLo;
printf("StartAddr = %x\n", start_addr);
if (start_addr == 0xffff) {
printf("Oops thats a header\n");
state = Expect_StartLo;
}
break;
case Expect_FinishLo:
finish_addr = (finish_addr & 0xff00) | byte;
state = Expect_FinishHi;
break;
case Expect_FinishHi:
finish_addr = (finish_addr & 0x00ff) | (byte << 8);
state = Expect_Data;
addr = start_addr;
printf("FinishAddr = %x\n", finish_addr);
break;
case Expect_Data:
image[addr++] = byte;
if (addr > finish_addr)
state = Expect_StartLo;
break;
default:
printf("Error: Invalid State\n");
return 1;
}
}
fclose(f);
/*
* Write image to file
*/
if (image_filename) {
f = fopen(image_filename, "wb");
if (!f) {
perror(image_filename);
return 1;
}
fwrite(&image[addr1], 1, addr2 - addr1 + 1, f);
fclose(f);
}
if (header_filename) {
FILE *fp;
char *ptr;
int j;
fp = fopen(header_filename, "wb");
if (!fp) {
perror(header_filename);
return 1;
}
for (ptr = header_filename; *ptr; ptr++) {
if (!( (*ptr >= 'a' && *ptr <= 'z')
|| (*ptr >= 'A' && *ptr <= 'Z')
|| (*ptr >= '0' && *ptr <= '9') ))
*ptr = '_';
}
fprintf(fp, "#ifndef _%s_\n", header_filename);
fprintf(fp, "#define _%s_\n\n", header_filename);
fprintf(fp, "static unsigned char %s[] =\n{\n\t", header_filename);
for (i = addr1, j = 0; i < addr2; i++) {
fprintf(fp, "0x%02x,", image[i]);
if (++j == 8) {
fprintf(fp, "\n\t");
j = 0;
}
}
fprintf(fp, "0x%02x\n", image[addr2]);
fprintf(fp, "};\n");
fprintf(fp, "\n#endif\n");
fclose(fp);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
#ifndef MONITOR_H_
#define MONITOR_H_
#include "config.h"
#include <stdio.h>
#include "atari.h"
int MONITOR_Run(void);
#ifdef MONITOR_TRACE
extern FILE *MONITOR_trace_file;
#endif
#ifdef MONITOR_BREAK
extern UWORD MONITOR_break_addr;
extern UBYTE MONITOR_break_step;
extern UBYTE MONITOR_break_ret;
extern UBYTE MONITOR_break_brk;
extern int MONITOR_ret_nesting;
#endif
extern const UBYTE MONITOR_optype6502[256];
void MONITOR_ShowState(FILE *fp, UWORD pc, UBYTE a, UBYTE x, UBYTE y, UBYTE s,
char n, char v, char z, char c);
#ifdef MONITOR_BREAKPOINTS
/* Breakpoint conditions */
#define MONITOR_BREAKPOINT_OR 1
#define MONITOR_BREAKPOINT_FLAG_CLEAR 2
#define MONITOR_BREAKPOINT_FLAG_SET 3
/* these three may be ORed together and must be ORed with MONITOR_BREAKPOINT_PC .. MONITOR_BREAKPOINT_WRITE */
#define MONITOR_BREAKPOINT_LESS 1
#define MONITOR_BREAKPOINT_EQUAL 2
#define MONITOR_BREAKPOINT_GREATER 4
#define MONITOR_BREAKPOINT_PC 8
#define MONITOR_BREAKPOINT_A 16
#define MONITOR_BREAKPOINT_X 32
#define MONITOR_BREAKPOINT_Y 40
#define MONITOR_BREAKPOINT_S 48
#define MONITOR_BREAKPOINT_READ 64
#define MONITOR_BREAKPOINT_WRITE 128
#define MONITOR_BREAKPOINT_ACCESS (MONITOR_BREAKPOINT_READ | MONITOR_BREAKPOINT_WRITE)
typedef struct {
UBYTE enabled;
UBYTE condition;
UWORD value;
} MONITOR_breakpoint_cond;
#define MONITOR_BREAKPOINT_TABLE_MAX 20
extern MONITOR_breakpoint_cond MONITOR_breakpoint_table[MONITOR_BREAKPOINT_TABLE_MAX];
extern int MONITOR_breakpoint_table_size;
extern int MONITOR_breakpoints_enabled;
#endif /* MONITOR_BREAKPOINTS */
#endif /* MONITOR_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
#ifndef MZPOKEYSND_H_
#define MZPOKEYSND_H_
#include "config.h"
#include "pokeysnd.h"
#include "atari.h"
int MZPOKEYSND_Init(ULONG freq17,
int playback_freq,
UBYTE num_pokeys,
int flags,
int quality
#ifdef __PLUS
, int clear_regs
#endif
);
#endif /* MZPOKEYSND_H_ */

View File

@@ -1,301 +0,0 @@
/*
* pbi.c - Parallel bus emulation
*
* Copyright (C) 2002 Jason Duerstock <jason@cluephone.com>
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 2002-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "pbi.h"
#include "memory.h"
#include "pia.h"
#include "cpu.h"
#include "log.h"
#include "util.h"
#include "statesav.h"
#include <stdlib.h>
#ifdef PBI_MIO
#include "pbi_mio.h"
#endif
#ifdef PBI_BB
#include "pbi_bb.h"
#endif
#ifdef PBI_XLD
#include "pbi_xld.h"
#endif
#ifdef PBI_PROTO80
#include "pbi_proto80.h"
#endif
/* stores the current state of the D1FF register, real hardware has 1
* bit per device, the bits are on the devices themselves */
static UBYTE D1FF_LATCH = 0;
/* 1400XL/1450XLD and 1090 have ram here */
int PBI_D6D7ram = FALSE;
/* So far as is currently implemented: PBI_IRQ can be generated by the 1400/1450 Votrax and the Black Box button */
/* Each emulated PBI device will set a bit in this variable to indicate IRQ status */
/* The actual hardware has only one common line. The device driver rom has to
* figure it out*/
int PBI_IRQ = 0;
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
int PBI_Initialise(int *argc, char *argv[])
{
return TRUE
#ifdef PBI_XLD
&& PBI_XLD_Initialise(argc, argv)
#endif
#ifdef PBI_BB
&& PBI_BB_Initialise(argc, argv)
#endif
#ifdef PBI_MIO
&& PBI_MIO_Initialise(argc, argv)
#endif
#ifdef PBI_PROTO80
&& PBI_PROTO80_Initialise(argc, argv)
#endif
;
}
int PBI_ReadConfig(char *string, char *ptr)
{
if (0) {
}
#ifdef PBI_XLD
else if (PBI_XLD_ReadConfig(string, ptr)) {
}
#endif
#ifdef PBI_MIO
else if (PBI_MIO_ReadConfig(string, ptr)) {
}
#endif
#ifdef PBI_BB
else if (PBI_BB_ReadConfig(string, ptr)) {
}
#endif
#ifdef PBI_PROTO80
else if (PBI_PROTO80_ReadConfig(string, ptr)) {
}
#endif
else return FALSE; /* no match */
return TRUE; /* matched something */
}
void PBI_WriteConfig(FILE *fp)
{
#ifdef PBI_MIO
PBI_MIO_WriteConfig(fp);
#endif
#ifdef PBI_BB
PBI_BB_WriteConfig(fp);
#endif
#ifdef PBI_XLD
PBI_XLD_WriteConfig(fp);
#endif
#ifdef PBI_PROTO80
PBI_PROTO80_WriteConfig(fp);
#endif
}
void PBI_Reset(void)
{
/* Reset all PBI ROMs */
PBI_D1PutByte(0xd1ff, 0);
#ifdef PBI_XLD
if (PBI_XLD_enabled) PBI_XLD_Reset();
#endif
PBI_IRQ = 0;
}
UBYTE PBI_D1GetByte(UWORD addr)
{
int result = 0xff;
/* MIO and BB do not follow the spec, they take over the bus: */
#ifdef PBI_MIO
if (PBI_MIO_enabled) return PBI_MIO_D1GetByte(addr);
#endif
#ifdef PBI_BB
if (PBI_BB_enabled) return PBI_BB_D1GetByte(addr);
#endif
/* Remaining PBI devices cooperate, following spec */
#ifdef PBI_XLD
if (PBI_XLD_enabled) result = PBI_XLD_D1GetByte(addr);
#endif
#ifdef PBI_PROTO80
if (result == PBI_NOT_HANDLED && PBI_PROTO80_enabled) result = PBI_PROTO80_D1GetByte(addr);
#endif
if(result != PBI_NOT_HANDLED) return (UBYTE)result;
/* Each bit of D1FF is set by one of the 8 PBI devices to signal IRQ */
/* The XLD devices have been combined into a single handler */
if (addr == 0xd1ff) {
/* D1FF IRQ status: */
result = 0;
#ifdef PBI_XLD
if (PBI_XLD_enabled) result |= PBI_XLD_D1ffGetByte();
#endif
/* add more devices here... */
return result;
}
/* addr was not handled: */
D(printf("PBI_GetByte:%4x:%2x PC:%4x IRQ:%d\n",addr,result,CPU_regPC,IRQ));
return result; /* 0xff */
}
void PBI_D1PutByte(UWORD addr, UBYTE byte)
{
static int fp_active = TRUE;
#ifdef PBI_MIO
if (PBI_MIO_enabled) {
PBI_MIO_D1PutByte(addr, byte);
return;
}
#endif
#ifdef PBI_BB
if (PBI_BB_enabled) {
PBI_BB_D1PutByte(addr, byte);
return;
}
#endif
/* Remaining PBI devices cooperate, following spec */
if (addr != 0xd1ff) {
D(printf("PBI_PutByte:%4x <- %2x\n", addr, byte));
#ifdef PBI_XLD
if (PBI_XLD_enabled) PBI_XLD_D1PutByte(addr, byte);
#endif
#ifdef PBI_PROTO_80
if (PBI_PROTO80_enabled) PBI_PROTO80_D1PutByte(addr, byte);
#endif
/* add more devices here... */
}
else if (addr == 0xd1ff) {
/* D1FF pbi rom bank select */
D(printf("D1FF write:%x\n", byte));
if (D1FF_LATCH != byte) {
/* if it's not valid, ignore it */
if (byte != 0 && byte != 1 && byte != 2 && byte != 4 && byte != 8 && byte != 0x10 && byte !=0x20 && byte != 0x40 && byte != 0x80){
D(printf("*****INVALID d1ff write:%2x********\n",byte));
return;
}
/* otherwise, update the latch */
D1FF_LATCH = byte;
#ifdef PBI_XLD
if (PBI_XLD_enabled && PBI_XLD_D1ffPutByte(byte) != PBI_NOT_HANDLED) {
/* handled */
fp_active = FALSE;
return;
}
#endif
#ifdef PBI_PROTO80
if (PBI_PROTO80_enabled && PBI_PROTO80_D1ffPutByte(byte) != PBI_NOT_HANDLED) {
/* handled */
fp_active = FALSE;
return;
}
#endif
/* add more devices here... */
/* reactivate the floating point rom */
if (!fp_active) {
memcpy(MEMORY_mem + 0xd800, MEMORY_os + 0x1800, 0x800);
D(printf("Floating point rom activated\n"));
fp_active = TRUE;
}
}
}
}
/* $D6xx */
UBYTE PBI_D6GetByte(UWORD addr)
{
#ifdef PBI_MIO
if (PBI_MIO_enabled) return PBI_MIO_D6GetByte(addr);
#endif
#ifdef PBI_BB
if(PBI_BB_enabled) return PBI_BB_D6GetByte(addr);
#endif
/* XLD/1090 has ram here */
if (PBI_D6D7ram) return MEMORY_mem[addr];
else return 0xff;
}
/* $D6xx */
void PBI_D6PutByte(UWORD addr, UBYTE byte)
{
#ifdef PBI_MIO
if (PBI_MIO_enabled) {
PBI_MIO_D6PutByte(addr,byte);
return;
}
#endif
#ifdef PBI_BB
if(PBI_BB_enabled) {
PBI_BB_D6PutByte(addr,byte);
return;
}
#endif
/* XLD/1090 has ram here */
if (PBI_D6D7ram) MEMORY_mem[addr]=byte;
}
/* read page $D7xx */
/* XLD/1090 has ram here */
UBYTE PBI_D7GetByte(UWORD addr)
{
D(printf("PBI_D7GetByte:%4x\n",addr));
if (PBI_D6D7ram) return MEMORY_mem[addr];
else return 0xff;
}
/* write page $D7xx */
/* XLD/1090 has ram here */
void PBI_D7PutByte(UWORD addr, UBYTE byte)
{
D(printf("PBI_D7PutByte:%4x <- %2x\n",addr,byte));
if (PBI_D6D7ram) MEMORY_mem[addr]=byte;
}
#ifndef BASIC
void PBI_StateSave(void)
{
StateSav_SaveUBYTE(&D1FF_LATCH, 1);
StateSav_SaveINT(&PBI_D6D7ram, 1);
StateSav_SaveINT(&PBI_IRQ, 1);
}
void PBI_StateRead(void)
{
StateSav_ReadUBYTE(&D1FF_LATCH, 1);
StateSav_ReadINT(&PBI_D6D7ram, 1);
StateSav_ReadINT(&PBI_IRQ, 1);
}
#endif /* #ifndef BASIC */
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,23 +0,0 @@
#ifndef PBI_H_
#define PBI_H_
#include "atari.h"
#include <stdio.h>
int PBI_Initialise(int *argc, char *argv[]);
int PBI_ReadConfig(char *string, char *ptr);
void PBI_WriteConfig(FILE *fp);
void PBI_Reset(void);
UBYTE PBI_D1GetByte(UWORD addr);
void PBI_D1PutByte(UWORD addr, UBYTE byte);
UBYTE PBI_D6GetByte(UWORD addr);
void PBI_D6PutByte(UWORD addr, UBYTE byte);
UBYTE PBI_D7GetByte(UWORD addr);
void PBI_D7PutByte(UWORD addr, UBYTE byte);
extern int PBI_IRQ;
extern int PBI_D6D7ram;
void PBI_StateSave(void);
void PBI_StateRead(void);
#define PBI_NOT_HANDLED -1
/* #define PBI_DEBUG */
#endif /* PBI_H_ */

View File

@@ -1,314 +0,0 @@
/*
* pbi_bb.c - CSS Black Box emulation
*
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "pbi_bb.h"
#include "util.h"
#include "log.h"
#include "pbi.h"
#include "memory.h"
#include "pia.h"
#include "pokey.h"
#include "cpu.h"
#include "pbi_scsi.h"
#include "statesav.h"
#include "util.h"
#include <stdlib.h>
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
/* CSS Black Box emulation */
/* information source: http://www.mathyvannisselroy.nl/bbdoku.txt*/
#define BB_BUTTON_IRQ_MASK 1
int PBI_BB_enabled = FALSE;
static UBYTE *bb_rom;
static int bb_ram_bank_offset = 0;
static UBYTE *bb_ram;
#define BB_RAM_SIZE 0x10000
static UBYTE bb_rom_bank = 0;
static int bb_rom_size;
static int bb_rom_high_bit = 0x00;/*0x10*/
static char bb_rom_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static UBYTE bb_PCR = 0; /* VIA Peripheral control register*/
static int bb_scsi_enabled = FALSE;
static char bb_scsi_disk_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static void init_bb(void)
{
FILE *bbfp;
bbfp = fopen(bb_rom_filename,"rb");
bb_rom_size = Util_flen(bbfp);
fclose(bbfp);
if (bb_rom_size != 0x10000 && bb_rom_size != 0x4000) {
Log_print("Invalid black box rom size\n");
return;
}
bb_rom = (UBYTE *)Util_malloc(bb_rom_size);
if (!Atari800_LoadImage(bb_rom_filename, bb_rom, bb_rom_size)) {
free(bb_rom);
return;
}
D(printf("loaded black box rom image\n"));
PBI_BB_enabled = TRUE;
if (PBI_SCSI_disk != NULL) fclose(PBI_SCSI_disk);
if (!Util_filenamenotset(bb_scsi_disk_filename)) {
PBI_SCSI_disk = fopen(bb_scsi_disk_filename, "rb+");
if (PBI_SCSI_disk == NULL) {
Log_print("Error opening BB SCSI disk image:%s", bb_scsi_disk_filename);
}
else {
D(printf("Opened BB SCSI disk image\n"));
bb_scsi_enabled = TRUE;
}
}
if (!bb_scsi_enabled) {
PBI_SCSI_BSY = TRUE; /* makes BB give up easier? */
}
bb_ram = (UBYTE *)Util_malloc(BB_RAM_SIZE);
memset(bb_ram,0,BB_RAM_SIZE);
}
int PBI_BB_Initialise(int *argc, char *argv[])
{
int i, j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-bb") == 0) {
init_bb();
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-bb Emulate the CSS Black Box");
}
argv[j++] = argv[i];
}
}
*argc = j;
return TRUE;
}
int PBI_BB_ReadConfig(char *string, char *ptr)
{
if (strcmp(string, "BLACK_BOX_ROM") == 0)
Util_strlcpy(bb_rom_filename, ptr, sizeof(bb_rom_filename));
else if (strcmp(string, "BB_SCSI_DISK") == 0)
Util_strlcpy(bb_scsi_disk_filename, ptr, sizeof(bb_scsi_disk_filename));
else return FALSE; /* no match */
return TRUE; /* matched something */
}
void PBI_BB_WriteConfig(FILE *fp)
{
fprintf(fp, "BLACK_BOX_ROM=%s\n", bb_rom_filename);
if (!Util_filenamenotset(bb_scsi_disk_filename)) {
fprintf(fp, "BB_SCSI_DISK=%s\n", bb_scsi_disk_filename);
}
}
UBYTE PBI_BB_D1GetByte(UWORD addr)
{
UBYTE result = 0x00;/*ff;*/
if (addr == 0xd1be) result = 0xff;
else if (addr == 0xd170) {
/* status */
result = ((!(PBI_SCSI_REQ))<<7)|((!PBI_SCSI_BSY)<<6)|((!PBI_SCSI_SEL)<<2)|((!PBI_SCSI_CD)<<1)|(!PBI_SCSI_IO);
}
else if (addr == 0xd171) {
if (bb_scsi_enabled) {
result = PBI_SCSI_GetByte();
if (((bb_PCR & 0x0e)>>1) == 0x04) {
/* handshake output */
PBI_SCSI_PutACK(1);
PBI_SCSI_PutACK(0);
}
}
}
else if (addr == 0xd1bc) result = (bb_ram_bank_offset >> 8);/*RAMPAGE*/
else if (addr == 0xd1be) {
/* SWITCH */
result = 0x02;
}
else if (addr == 0xd1ff) result = PBI_IRQ ? (0x08 | 0x02) : 0 ;
D(if (addr!=0xd1ff) printf("BB Read:%4x PC:%4x byte=%2x\n", addr, CPU_remember_PC[(CPU_remember_PC_curpos-1)%CPU_REMEMBER_PC_STEPS], result));
return result;
}
void PBI_BB_D1PutByte(UWORD addr, UBYTE byte)
{
D(printf("BB Write addr:%4x byte:%2x, cpu:%4x\n", addr, byte, CPU_remember_PC[(CPU_remember_PC_curpos-1)%CPU_REMEMBER_PC_STEPS]));
if (addr == 0xd170) {
if (bb_scsi_enabled) PBI_SCSI_PutSEL(!(byte&0x04));
}
else if (addr == 0xd171) {
if (bb_scsi_enabled) {
PBI_SCSI_PutByte(byte);
if (((bb_PCR & 0x0e)>>1) == 0x04) {
/* handshake output */
PBI_SCSI_PutACK(1);
PBI_SCSI_PutACK(0);
}
}
}
else if (addr == 0xd17c) { /* PCR */
bb_PCR = byte;
if (((bb_PCR & 0x0e)>>1) == 0x06) {
/* low output */
if (bb_scsi_enabled) PBI_SCSI_PutACK(1);
}
else if (((bb_PCR & 0x0e)>>1) == 0x07) {
/* high output */
if (bb_scsi_enabled) PBI_SCSI_PutACK(0);
}
}
else if (addr == 0xd1bc) {
/* RAMPAGE */
/* Copy old page to buffer, Copy new page from buffer */
memcpy(bb_ram+bb_ram_bank_offset,MEMORY_mem + 0xd600,0x100);
bb_ram_bank_offset = (byte << 8);
memcpy(MEMORY_mem + 0xd600, bb_ram+bb_ram_bank_offset, 0x100);
}
else if (addr == 0xd1be) {
/* high rom bit */
if (bb_rom_high_bit != ((byte & 0x04) << 2) && bb_rom_size == 0x10000) {
/* high bit has changed */
bb_rom_high_bit = ((byte & 0x04) << 2);
if (bb_rom_bank > 0 && bb_rom_bank < 8) {
memcpy(MEMORY_mem + 0xd800, bb_rom + (bb_rom_bank + bb_rom_high_bit)*0x800, 0x800);
D(printf("black box bank:%2x activated\n", bb_rom_bank+bb_rom_high_bit));
}
}
}
else if ((addr & 0xffc0) == 0xd1c0) {
/* byte &= 0x0f; */
if (bb_rom_bank != byte) {
/* PDVS (d1ff) rom bank */
int offset = -1;
if (bb_rom_size == 0x4000) {
if (byte >= 8 && byte <= 0x0f) offset = (byte - 8)*0x800;
else if (byte > 0 && byte < 0x08) offset = byte*0x800;
}
else { /* bb_rom_size == 0x10000 */
if (byte > 0 && byte < 0x10) offset = (byte + bb_rom_high_bit)*0x800;
}
if (offset != -1) {
memcpy(MEMORY_mem + 0xd800, bb_rom + offset, 0x800);
D(printf("black box bank:%2x activated\n", byte + bb_rom_high_bit));
}
else {
memcpy(MEMORY_mem + 0xd800, MEMORY_os + 0x1800, 0x800);
if (byte != 0) D(printf("d1ff ERROR: byte=%2x\n", byte));
D(printf("Floating point rom activated\n"));
}
bb_rom_bank = byte;
}
}
}
/* Black Box RAM page at D600-D6ff*/
/* Possible to put code in this ram, so we can't avoid using MEMORY_mem[]
* because opcode fetch doesn't call this function*/
UBYTE PBI_BB_D6GetByte(UWORD addr)
{
return MEMORY_mem[addr];
}
/* $D6xx */
void PBI_BB_D6PutByte(UWORD addr, UBYTE byte)
{
MEMORY_mem[addr]=byte;
}
static int buttondown;
void PBI_BB_Menu(void)
{
if (!PBI_BB_enabled) return;
if (buttondown == FALSE) {
D(printf("blackbox button down interrupt generated\n"));
CPU_GenerateIRQ();
PBI_IRQ |= BB_BUTTON_IRQ_MASK;
buttondown = TRUE;
}
}
void PBI_BB_Frame(void)
{
static int count = 0;
if (buttondown) {
if (count < 1) count++;
else {
D(printf("blackbox button up\n"));
PBI_IRQ &= ~BB_BUTTON_IRQ_MASK;
/* update pokey IRQ status */
POKEY_PutByte(POKEY_OFFSET_IRQEN, POKEY_IRQEN);
buttondown = FALSE;
count = 0;
}
}
}
#ifndef BASIC
void PBI_BB_StateSave(void)
{
StateSav_SaveINT(&PBI_BB_enabled, 1);
if (PBI_BB_enabled) {
StateSav_SaveFNAME(bb_scsi_disk_filename);
StateSav_SaveFNAME(bb_rom_filename);
StateSav_SaveINT(&bb_ram_bank_offset, 1);
StateSav_SaveUBYTE(bb_ram, BB_RAM_SIZE);
StateSav_SaveUBYTE(&bb_rom_bank, 1);
StateSav_SaveINT(&bb_rom_high_bit, 1);
StateSav_SaveUBYTE(&bb_PCR, 1);
}
}
void PBI_BB_StateRead(void)
{
StateSav_ReadINT(&PBI_BB_enabled, 1);
if (PBI_BB_enabled) {
StateSav_ReadFNAME(bb_scsi_disk_filename);
StateSav_ReadFNAME(bb_rom_filename);
init_bb();
StateSav_ReadINT(&bb_ram_bank_offset, 1);
StateSav_ReadUBYTE(bb_ram, BB_RAM_SIZE);
StateSav_ReadUBYTE(&bb_rom_bank, 1);
StateSav_ReadINT(&bb_rom_high_bit, 1);
StateSav_ReadUBYTE(&bb_PCR, 1);
}
}
#endif /* #ifndef BASIC */
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,20 +0,0 @@
#ifndef PBI_BB_H_
#define PBI_BB_H_
#include "atari.h"
#include <stdio.h>
extern int PBI_BB_enabled;
void PBI_BB_Menu(void);
void PBI_BB_Frame(void);
int PBI_BB_Initialise(int *argc, char *argv[]);
UBYTE PBI_BB_D1GetByte(UWORD addr);
void PBI_BB_D1PutByte(UWORD addr, UBYTE byte);
UBYTE PBI_BB_D6GetByte(UWORD addr);
void PBI_BB_D6PutByte(UWORD addr, UBYTE byte);
int PBI_BB_ReadConfig(char *string, char *ptr);
void PBI_BB_WriteConfig(FILE *fp);
void PBI_BB_StateSave(void);
void PBI_BB_StateRead(void);
#endif /* PBI_BB_H_ */

View File

@@ -1,258 +0,0 @@
/*
* pbi_mio.c - ICD MIO board emulation
*
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "pbi_mio.h"
#include "util.h"
#include "log.h"
#include "memory.h"
#include "pia.h"
#include "pbi.h"
#include "cpu.h"
#include "stdlib.h"
#include "pbi_scsi.h"
#include "statesav.h"
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
int PBI_MIO_enabled = FALSE;
static UBYTE *mio_rom;
static int mio_rom_size = 0x4000;
static int mio_ram_bank_offset = 0;
static UBYTE *mio_ram;
static int mio_ram_size = 0x100000;
static UBYTE mio_rom_bank = 0;
static int mio_ram_enabled = FALSE;
static char mio_rom_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static char mio_scsi_disk_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static int mio_scsi_enabled = FALSE;
static void init_mio(void)
{
free(mio_rom);
mio_rom = (UBYTE *)Util_malloc(mio_rom_size);
if (!Atari800_LoadImage(mio_rom_filename, mio_rom, mio_rom_size)) {
free(mio_rom);
return;
}
D(printf("Loaded mio rom image\n"));
PBI_MIO_enabled = TRUE;
if (PBI_SCSI_disk != NULL) fclose(PBI_SCSI_disk);
if (!Util_filenamenotset(mio_scsi_disk_filename)) {
PBI_SCSI_disk = fopen(mio_scsi_disk_filename, "rb+");
if (PBI_SCSI_disk == NULL) {
Log_print("Error opening SCSI disk image:%s", mio_scsi_disk_filename);
}
else {
D(printf("Opened SCSI disk image\n"));
mio_scsi_enabled = TRUE;
}
}
if (!mio_scsi_enabled) {
PBI_SCSI_BSY = TRUE; /* makes MIO give up easier */
}
free(mio_ram);
mio_ram = (UBYTE *)Util_malloc(mio_ram_size);
memset(mio_ram, 0, mio_ram_size);
}
int PBI_MIO_Initialise(int *argc, char *argv[])
{
int i, j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-mio") == 0) {
init_mio();
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-mio Emulate the ICD MIO board");
}
argv[j++] = argv[i];
}
}
*argc = j;
return TRUE;
}
int PBI_MIO_ReadConfig(char *string, char *ptr)
{
if (strcmp(string, "MIO_ROM") == 0)
Util_strlcpy(mio_rom_filename, ptr, sizeof(mio_rom_filename));
else if (strcmp(string, "MIO_SCSI_DISK") == 0)
Util_strlcpy(mio_scsi_disk_filename, ptr, sizeof(mio_scsi_disk_filename));
else return FALSE; /* no match */
return TRUE; /* matched something */
}
void PBI_MIO_WriteConfig(FILE *fp)
{
fprintf(fp, "MIO_ROM=%s\n", mio_rom_filename);
if (!Util_filenamenotset(mio_scsi_disk_filename)) {
fprintf(fp, "MIO_SCSI_DISK=%s\n", mio_scsi_disk_filename);
}
}
/* $D1xx */
UBYTE PBI_MIO_D1GetByte(UWORD addr)
{
UBYTE result = 0x00;/*ff*/;
addr &= 0xffe3; /* 7 mirrors */
D(printf("MIO Read:%4x PC:%4x\n", addr, CPU_remember_PC[(CPU_remember_PC_curpos-1)%CPU_REMEMBER_PC_STEPS]));
if (addr == 0xd1e2) {
result = ((!PBI_SCSI_CD) | (!PBI_SCSI_MSG<<1) | (!PBI_SCSI_IO<<2) | (!PBI_SCSI_BSY<<5) | (!PBI_SCSI_REQ<<7));
}
else if (addr == 0xd1e1) {
if (mio_scsi_enabled) {
result = PBI_SCSI_GetByte()^0xff;
PBI_SCSI_PutACK(1);
PBI_SCSI_PutACK(0);
}
}
return result;
}
/* $D1xx */
void PBI_MIO_D1PutByte(UWORD addr, UBYTE byte)
{
int old_mio_ram_bank_offset = mio_ram_bank_offset;
int old_mio_ram_enabled = mio_ram_enabled;
int offset_changed;
int ram_enabled_changed;
addr &= 0xffe3; /* 7 mirrors */
if (addr == 0xd1e0) {
/* ram bank A15-A8 */
mio_ram_bank_offset &= 0xf0000;
mio_ram_bank_offset |= (byte << 8);
}
else if (addr == 0xd1e1) {
if (mio_scsi_enabled) {
PBI_SCSI_PutByte(byte^0xff);
PBI_SCSI_PutACK(1);
PBI_SCSI_PutACK(0);
}
}
else if (addr == 0xd1e2) {
/* ram bank A19-A16, ram enable, other stuff */
mio_ram_bank_offset &= 0x0ffff;
mio_ram_bank_offset |= ( (byte & 0x0f) << 16);
mio_ram_enabled = (byte & 0x20);
if (mio_scsi_enabled) PBI_SCSI_PutSEL(!!(byte & 0x10));
}
else if (addr == 0xd1e3) {
/* or 0xd1ff. rom bank. */
if (mio_rom_bank != byte){
int offset = -1;
if (byte == 4) offset = 0x2000;
else if (byte == 8) offset = 0x2800;
else if (byte == 0x10) offset = 0x3000;
else if (byte == 0x20) offset = 0x3800;
if (offset != -1) {
memcpy(MEMORY_mem + 0xd800, mio_rom+offset, 0x800);
D(printf("mio bank:%2x activated\n", byte));
}else{
memcpy(MEMORY_mem + 0xd800, MEMORY_os + 0x1800, 0x800);
D(printf("Floating point rom activated\n"));
}
mio_rom_bank = byte;
}
}
offset_changed = (old_mio_ram_bank_offset != mio_ram_bank_offset);
ram_enabled_changed = (old_mio_ram_enabled != mio_ram_enabled);
if (mio_ram_enabled && ram_enabled_changed) {
/* Copy new page from buffer, overwrite ff page */
memcpy(MEMORY_mem + 0xd600, mio_ram + mio_ram_bank_offset, 0x100);
} else if (mio_ram_enabled && offset_changed) {
/* Copy old page to buffer, copy new page from buffer */
memcpy(mio_ram + old_mio_ram_bank_offset,MEMORY_mem + 0xd600, 0x100);
memcpy(MEMORY_mem + 0xd600, mio_ram + mio_ram_bank_offset, 0x100);
} else if (!mio_ram_enabled && ram_enabled_changed) {
/* Copy old page to buffer, set new page to ff */
memcpy(mio_ram + old_mio_ram_bank_offset, MEMORY_mem + 0xd600, 0x100);
memset(MEMORY_mem + 0xd600, 0xff, 0x100);
}
D(printf("MIO Write addr:%4x byte:%2x, cpu:%4x\n", addr, byte,CPU_remember_PC[(CPU_remember_PC_curpos-1)%CPU_REMEMBER_PC_STEPS]));
}
/* MIO RAM page at D600-D6ff */
/* Possible to put code in this ram, so we can't avoid using MEMORY_mem[] */
/* because opcode fetch doesn't call this function */
UBYTE PBI_MIO_D6GetByte(UWORD addr)
{
if (!mio_ram_enabled) return 0xff;
return MEMORY_mem[addr];
}
/* $D6xx */
void PBI_MIO_D6PutByte(UWORD addr, UBYTE byte)
{
if (!mio_ram_enabled) return;
MEMORY_mem[addr]=byte;
}
#ifndef BASIC
void PBI_MIO_StateSave(void)
{
StateSav_SaveINT(&PBI_MIO_enabled, 1);
if (PBI_MIO_enabled) {
StateSav_SaveFNAME(mio_scsi_disk_filename);
StateSav_SaveFNAME(mio_rom_filename);
StateSav_SaveINT(&mio_ram_size, 1);
StateSav_SaveINT(&mio_ram_bank_offset, 1);
StateSav_SaveUBYTE(mio_ram, mio_ram_size);
StateSav_SaveUBYTE(&mio_rom_bank, 1);
StateSav_SaveINT(&mio_ram_enabled, 1);
}
}
void PBI_MIO_StateRead(void)
{
StateSav_ReadINT(&PBI_MIO_enabled, 1);
if (PBI_MIO_enabled) {
StateSav_ReadFNAME(mio_scsi_disk_filename);
StateSav_ReadFNAME(mio_rom_filename);
StateSav_ReadINT(&mio_ram_size, 1);
init_mio();
StateSav_ReadINT(&mio_ram_bank_offset, 1);
StateSav_ReadUBYTE(mio_ram, mio_ram_size);
StateSav_ReadUBYTE(&mio_rom_bank, 1);
StateSav_ReadINT(&mio_ram_enabled, 1);
}
}
#endif /* #ifndef BASIC */
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,19 +0,0 @@
#ifndef PBI_MIO_H_
#define PBI_MIO_H_
#include "atari.h"
#include <stdio.h>
extern int PBI_MIO_enabled;
int PBI_MIO_Initialise(int *argc, char *argv[]);
UBYTE PBI_MIO_D1GetByte(UWORD addr);
void PBI_MIO_D1PutByte(UWORD addr, UBYTE byte);
UBYTE PBI_MIO_D6GetByte(UWORD addr);
void PBI_MIO_D6PutByte(UWORD addr, UBYTE byte);
int PBI_MIO_ReadConfig(char *string, char *ptr);
void PBI_MIO_WriteConfig(FILE *fp);
void PBI_MIO_StateSave(void);
void PBI_MIO_StateRead(void);
#endif /* PBI_MIO_H_ */

View File

@@ -1,144 +0,0 @@
/*
* pbi_proto.c - Emulation of a prototype 80 column board for the
* Atari 1090 expansion interface.
*
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 2002-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "pbi.h"
#include "pbi_proto80.h"
#include "util.h"
#include "log.h"
#include "memory.h"
#include <stdlib.h>
#define PROTO80_PBI_NUM 2
#define PROTO80_MASK (1 << PROTO80_PBI_NUM)
static UBYTE *proto80rom;
static char proto80_rom_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
int PBI_PROTO80_enabled = FALSE;
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
int PBI_PROTO80_Initialise(int *argc, char *argv[])
{
int i, j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-proto80") == 0) {
Log_print("proto80 enabled");
PBI_PROTO80_enabled = TRUE;
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-proto80 Emulate a prototype 80 column board for the 1090");
}
argv[j++] = argv[i];
}
}
*argc = j;
if (PBI_PROTO80_enabled) {
proto80rom = (UBYTE *)Util_malloc(0x800);
if (!Atari800_LoadImage(proto80_rom_filename, proto80rom, 0x800)) {
free(proto80rom);
PBI_PROTO80_enabled = FALSE;
Log_print("Couldn't load proto80 rom image");
return FALSE;
}
else {
Log_print("loaded proto80 rom image");
PBI_D6D7ram = TRUE;
}
}
return TRUE;
}
int PBI_PROTO80_ReadConfig(char *string, char *ptr)
{
if (strcmp(string, "PROTO80_ROM") == 0)
Util_strlcpy(proto80_rom_filename, ptr, sizeof(proto80_rom_filename));
else return FALSE; /* no match */
return TRUE; /* matched something */
}
void PBI_PROTO80_WriteConfig(FILE *fp)
{
fprintf(fp, "PROTO80_ROM=%s\n", proto80_rom_filename);
}
int PBI_PROTO80_D1GetByte(UWORD addr)
{
int result = PBI_NOT_HANDLED;
if (PBI_PROTO80_enabled) {
}
return result;
}
void PBI_PROTO80_D1PutByte(UWORD addr, UBYTE byte)
{
}
int PBI_PROTO80_D1ffPutByte(UBYTE byte)
{
int result = 0; /* handled */
if (PBI_PROTO80_enabled && byte == PROTO80_MASK) {
memcpy(MEMORY_mem + 0xd800, proto80rom, 0x800);
D(printf("PROTO80 rom activated\n"));
}
else result = PBI_NOT_HANDLED;
return result;
}
UBYTE PBI_PROTO80_GetPixels(int scanline, int column)
{
#define PROTO80_ROWS 24
#define PROTO80_CELL_HEIGHT 8
UBYTE character;
UBYTE invert;
UBYTE font_data;
int row = scanline / PROTO80_CELL_HEIGHT;
int line = scanline % PROTO80_CELL_HEIGHT;
if (row >= PROTO80_ROWS) {
return 0;
}
character = MEMORY_mem[0x9800 + row*80 + column];
invert = 0x00;
if (character & 0x80) {
invert = 0xff;
character &= 0x7f;
}
font_data = MEMORY_mem[0xe000 + character*8 + line];
font_data ^= invert;
return font_data;
}
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,14 +0,0 @@
#ifndef PBI_PROTO80_H_
#define PBI_PROTO80_H_
#include "atari.h"
int PBI_PROTO80_Initialise(int *argc, char *argv[]);
int PBI_PROTO80_ReadConfig(char *string, char *ptr);
void PBI_PROTO80_WriteConfig(FILE *fp);
int PBI_PROTO80_D1GetByte(UWORD addr);
void PBI_PROTO80_D1PutByte(UWORD addr, UBYTE byte);
int PBI_PROTO80_D1ffPutByte(UBYTE byte);
UBYTE PBI_PROTO80_GetPixels(int scanline, int column);
extern int PBI_PROTO80_enabled;
#endif /* PBI_PROTO80_H_ */

View File

@@ -1,241 +0,0 @@
/*
* pbi_scsi.c - SCSI emulation for the MIO and Black Box
*
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "util.h"
#include "log.h"
#include "pbi_scsi.h"
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
int PBI_SCSI_CD = FALSE;
int PBI_SCSI_MSG = FALSE;
int PBI_SCSI_IO = FALSE;
int PBI_SCSI_BSY = FALSE;
int PBI_SCSI_REQ = FALSE;
int PBI_SCSI_ACK = FALSE;
int PBI_SCSI_SEL = FALSE;
static UBYTE scsi_byte;
#define SCSI_PHASE_SELECTION 0
#define SCSI_PHASE_DATAIN 1
#define SCSI_PHASE_DATAOUT 2
#define SCSI_PHASE_COMMAND 3
#define SCSI_PHASE_STATUS 4
#define SCSI_PHASE_MSGIN 5
static int scsi_phase = SCSI_PHASE_SELECTION;
static int scsi_bufpos = 0;
static UBYTE scsi_buffer[256];
static int scsi_count = 0;
FILE *PBI_SCSI_disk = NULL;
static void scsi_changephase(int phase)
{
D(printf("scsi_changephase:%d\n",phase));
switch(phase) {
case SCSI_PHASE_SELECTION:
PBI_SCSI_REQ = FALSE;
PBI_SCSI_BSY = FALSE;
PBI_SCSI_CD = FALSE;
PBI_SCSI_IO = FALSE;
PBI_SCSI_MSG = FALSE;
break;
case SCSI_PHASE_DATAOUT:
PBI_SCSI_REQ = TRUE;
PBI_SCSI_BSY = TRUE;
PBI_SCSI_CD = FALSE;
PBI_SCSI_IO = FALSE;
PBI_SCSI_MSG = FALSE;
break;
case SCSI_PHASE_DATAIN:
PBI_SCSI_REQ = TRUE;
PBI_SCSI_BSY = TRUE;
PBI_SCSI_CD = FALSE;
PBI_SCSI_IO = TRUE;
PBI_SCSI_MSG = FALSE;
break;
case SCSI_PHASE_COMMAND:
PBI_SCSI_REQ = TRUE;
PBI_SCSI_BSY = TRUE;
PBI_SCSI_CD = TRUE;
PBI_SCSI_IO = FALSE;
PBI_SCSI_MSG = FALSE;
break;
case SCSI_PHASE_STATUS:
PBI_SCSI_REQ = TRUE;
PBI_SCSI_BSY = TRUE;
PBI_SCSI_CD = TRUE;
PBI_SCSI_IO = TRUE;
PBI_SCSI_MSG = FALSE;
break;
case SCSI_PHASE_MSGIN:
PBI_SCSI_REQ = TRUE;
PBI_SCSI_BSY = TRUE;
PBI_SCSI_CD = TRUE;
PBI_SCSI_IO = FALSE;
PBI_SCSI_MSG = TRUE;
break;
}
scsi_bufpos = 0;
scsi_phase = phase;
}
static void scsi_process_command(void)
{
int i;
int lba;
int lun;
D(printf("SCSI command:"));
for (i = 0; i < 6; i++) {
D(printf(" %02x",scsi_buffer[i]));
}
D(printf("\n"));
switch (scsi_buffer[0]) {
case 0x00:
/* test unit ready */
D(printf("SCSI: test unit ready\n"));
scsi_changephase(SCSI_PHASE_STATUS);
scsi_buffer[0] = 0;
break;
case 0x03:
/* request sense */
D(printf("SCSI: request sense\n"));
scsi_changephase(SCSI_PHASE_DATAIN);
memset(scsi_buffer,0,1);
scsi_count = 4;
break;
case 0x08:
/* read */
lun = ((scsi_buffer[1]&0xe0)>>5);
lba = (((scsi_buffer[1]&0x1f)<<16)|(scsi_buffer[2]<<8)|(scsi_buffer[3]));
D(printf("SCSI: read lun:%d lba:%d\n",lun,lba));
fseek(PBI_SCSI_disk, lba*256, SEEK_SET);
fread(scsi_buffer, 1, 256, PBI_SCSI_disk);
scsi_changephase(SCSI_PHASE_DATAIN);
scsi_count = 256;
break;
case 0x0a:
/* write */
lun = ((scsi_buffer[1]&0xe0)>>5);
lba = (((scsi_buffer[1]&0x1f)<<16)|(scsi_buffer[2]<<8)|(scsi_buffer[3]));
D(printf("SCSI: write lun:%d lba:%d\n",lun,lba));
fseek(PBI_SCSI_disk, lba*256, SEEK_SET);
scsi_changephase(SCSI_PHASE_DATAOUT);
scsi_count = 256;
break;
default:
D(printf("SCSI: unknown command:%2x\n", scsi_buffer[0]));
scsi_changephase(SCSI_PHASE_SELECTION);
break;
}
}
static void scsi_nextbyte(void)
{
if (scsi_phase == SCSI_PHASE_DATAIN) {
scsi_bufpos++;
if (scsi_bufpos >= scsi_count) {
scsi_changephase(SCSI_PHASE_STATUS);
scsi_buffer[0] = 0;
}
}
else if (scsi_phase == SCSI_PHASE_STATUS) {
D(printf("SCSI status\n"));
scsi_changephase(SCSI_PHASE_MSGIN);
scsi_buffer[0] = 0;
}
else if (scsi_phase == SCSI_PHASE_MSGIN) {
D(printf("SCSI msg\n"));
scsi_changephase(SCSI_PHASE_SELECTION);
}
else if (scsi_phase == SCSI_PHASE_COMMAND) {
scsi_buffer[scsi_bufpos++] = scsi_byte;
if (scsi_bufpos >= 0x06) {
scsi_process_command();
scsi_bufpos = 0;
}
}
else if (scsi_phase == SCSI_PHASE_DATAOUT) {
D(printf("SCSI data out:%2x\n", scsi_byte));
scsi_buffer[scsi_bufpos++] = scsi_byte;
if (scsi_bufpos >= scsi_count) {
fwrite(scsi_buffer, 1, 256, PBI_SCSI_disk);
scsi_changephase(SCSI_PHASE_STATUS);
scsi_buffer[0] = 0;
}
}
}
void PBI_SCSI_PutSEL(int newsel)
{
if (newsel != PBI_SCSI_SEL) {
/* SEL changed state */
PBI_SCSI_SEL = newsel;
if (PBI_SCSI_SEL && scsi_phase == SCSI_PHASE_SELECTION && scsi_byte == 0x01) {
scsi_changephase(SCSI_PHASE_COMMAND);
}
D(printf("changed SEL:%d scsi_byte:%2x\n",PBI_SCSI_SEL, scsi_byte));
}
}
void PBI_SCSI_PutACK(int newack)
{
if (newack != PBI_SCSI_ACK) {
/* ACK changed state */
PBI_SCSI_ACK = newack;
if (PBI_SCSI_ACK) {
/* REQ goes false when ACK goes true */
PBI_SCSI_REQ = FALSE;
}
else {
/* falling ACK triggers next byte */
if (scsi_phase != SCSI_PHASE_SELECTION) {
PBI_SCSI_REQ = TRUE;
scsi_nextbyte();
}
}
}
}
UBYTE PBI_SCSI_GetByte(void)
{
return (scsi_buffer[scsi_bufpos]);
}
void PBI_SCSI_PutByte(UBYTE byte)
{
scsi_byte = byte;
}
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,21 +0,0 @@
#ifndef PBI_SCSI_H_
#define PBI_SCSI_H_
#include "atari.h"
#include <stdio.h>
extern int PBI_SCSI_CD;
extern int PBI_SCSI_MSG;
extern int PBI_SCSI_IO;
extern int PBI_SCSI_BSY;
extern int PBI_SCSI_REQ;
extern int PBI_SCSI_SEL;
extern int PBI_SCSI_ACK;
extern FILE *PBI_SCSI_disk;
void PBI_SCSI_PutByte(UBYTE byte);
UBYTE PBI_SCSI_GetByte(void);
void PBI_SCSI_PutSEL(int newsel);
void PBI_SCSI_PutACK(int newack);
#endif /* PBI_MIO_H_ */

View File

@@ -1,921 +0,0 @@
/*
* pbi_xld.c - 1450XLD and 1400XL emulation
*
* Copyright (C) 2007-2008 Perry McFarlane
* Copyright (C) 2002-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "atari.h"
#include "votrax.h"
#include "pbi_xld.h"
#include "pbi.h"
#include "util.h"
#include "sio.h"
#include "log.h"
#include "pokey.h"
#include "cpu.h"
#include "memory.h"
#include "statesav.h"
#include <stdlib.h>
#define DISK_PBI_NUM 0
#define MODEM_PBI_NUM 1
#define VOICE_PBI_NUM 7
#define DISK_MASK (1 << DISK_PBI_NUM)
#define MODEM_MASK (1 << MODEM_PBI_NUM)
#define VOICE_MASK (1 << VOICE_PBI_NUM)
static UBYTE *voicerom;
static UBYTE *diskrom;
static char xld_d_rom_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static char xld_v_rom_filename[FILENAME_MAX] = Util_FILENAME_NOT_SET;
static UBYTE votrax_latch = 0;
static UBYTE modem_latch = 0;
int PBI_XLD_enabled = FALSE;
static int xld_v_enabled = FALSE;
static int xld_d_enabled = FALSE;
/* Parallel Disk I/O emulation support */
#define PIO_NoFrame (0x00)
#define PIO_CommandFrame (0x01)
#define PIO_StatusRead (0x02)
#define PIO_ReadFrame (0x03)
#define PIO_WriteFrame (0x04)
#define PIO_FinalStatus (0x05)
#define PIO_FormatFrame (0x06)
static UBYTE CommandFrame[6];
static int CommandIndex = 0;
static UBYTE DataBuffer[256 + 3];
static int DataIndex = 0;
static int TransferStatus = PIO_CommandFrame;
static int ExpectedBytes = 5;
static void PIO_PutByte(int byte);
static int PIO_GetByte(void);
static UBYTE PIO_Command_Frame(void);
/* Votrax */
static double ratio;
static int bit16;
#define VTRX_BLOCK_SIZE 1024
SWORD *temp_votrax_buffer = NULL;
SWORD *votrax_buffer = NULL;
static int votrax_busy = FALSE;
static volatile int votrax_written = FALSE;
static volatile int votrax_written_byte = 0x3f;
static int votrax_sync_samples;
static void votrax_busy_callback(int busy_status);
static int dsprate;
static int num_pokeys;
static int samples_per_frame;
#ifdef PBI_DEBUG
#define D(a) a
#else
#define D(a) do{}while(0)
#endif
#define VTRX_RATE 24500
static void init_xld_v(void)
{
free(voicerom);
voicerom = (UBYTE *)Util_malloc(0x1000);
if (!Atari800_LoadImage(xld_v_rom_filename, voicerom, 0x1000)) {
free(voicerom);
xld_v_enabled = FALSE;
}
else {
printf("loaded XLD voice rom image\n");
PBI_D6D7ram = TRUE;
}
votrax_busy = FALSE;
votrax_sync_samples = 0;
}
static void init_xld_d(void)
{
free(diskrom);
diskrom = (UBYTE *)Util_malloc(0x800);
if (!Atari800_LoadImage(xld_d_rom_filename, diskrom, 0x800)) {
free(diskrom);
xld_d_enabled = FALSE;
}
else {
D(printf("loaded 1450XLD D: device driver rom image\n"));
PBI_D6D7ram = TRUE;
}
}
int PBI_XLD_Initialise(int *argc, char *argv[])
{
int i, j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-1400") == 0) {
xld_v_enabled = TRUE;
PBI_XLD_enabled = TRUE;
}else if (strcmp(argv[i], "-xld") == 0){
xld_v_enabled = TRUE;
xld_d_enabled = TRUE;
PBI_XLD_enabled = TRUE;
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-1400 Emulate the Atari 1400XL");
Log_print("\t-xld Emulate the Atari 1450XLD");
}
argv[j++] = argv[i];
}
}
*argc = j;
if (xld_v_enabled) {
init_xld_v();
}
/* If you set the drive to empty in the UI, the message is displayed */
/* If you press select, I believe it tries to slow the I/O down */
/* in order to increase compatibility. */
/* dskcnt6 works. dskcnt10 does not */
if (xld_d_enabled) {
init_xld_d();
}
return TRUE;
}
int PBI_XLD_ReadConfig(char *string, char *ptr)
{
if (strcmp(string, "XLD_D_ROM") == 0)
Util_strlcpy(xld_d_rom_filename, ptr, sizeof(xld_d_rom_filename));
else if (strcmp(string, "XLD_V_ROM") == 0)
Util_strlcpy(xld_v_rom_filename, ptr, sizeof(xld_v_rom_filename));
else return FALSE; /* no match */
return TRUE; /* matched something */
}
void PBI_XLD_WriteConfig(FILE *fp)
{
fprintf(fp, "XLD_D_ROM=%s\n", xld_d_rom_filename);
fprintf(fp, "XLD_V_ROM=%s\n", xld_v_rom_filename);
}
void PBI_XLD_Reset(void)
{
votrax_latch = 0;
}
int PBI_XLD_D1GetByte(UWORD addr)
{
int result = PBI_NOT_HANDLED;
if (xld_d_enabled && addr == 0xd114) {
/* XLD input from disk to atari byte latch */
result = (int)PIO_GetByte();
D(printf("d114: disk read byte:%2x\n",result));
}
return result;
}
/* D1FF: each bit indicates IRQ status of a device */
UBYTE PBI_XLD_D1ffGetByte()
{
UBYTE result = 0;
/* VOTRAX BUSY IRQ bit */
/*if (!votraxsc01_status_r()) {*/
if (!votrax_busy) {
result |= VOICE_MASK;
}
return result;
}
void PBI_XLD_D1PutByte(UWORD addr, UBYTE byte)
{
if ((addr & ~3) == 0xd104) {
/* XLD disk strobe line */
D(printf("votrax write:%4x\n",addr));
votrax_sync_samples = (int)((1.0/ratio)*(double)Votrax_Samples(votrax_written_byte, votrax_latch & 0x3f, votrax_sync_samples));
votrax_written = TRUE;
votrax_written_byte = votrax_latch & 0x3f;
if (!votrax_busy) {
votrax_busy = TRUE;
votrax_busy_callback(TRUE); /* idle -> busy */
}
}
else if ((addr & ~3) == 0xd100 ) {
/* votrax phoneme+irq-enable latch */
if ( !(votrax_latch & 0x80) && (byte & 0x80) && (!Votrax_GetStatus())) {
/* IRQ disabled -> enabled, and votrax idle: generate IRQ */
D(printf("votrax IRQ generated: IRQ enable changed and idle\n"));
CPU_GenerateIRQ();
PBI_IRQ |= VOICE_MASK;
} else if ((votrax_latch & 0x80) && !(byte & 0x80) ){
/* IRQ enabled -> disabled : stop IRQ */
PBI_IRQ &= ~VOICE_MASK;
/* update pokey IRQ status */
POKEY_PutByte(POKEY_OFFSET_IRQEN, POKEY_IRQEN);
}
votrax_latch = byte;
}
else if (addr == 0xd108) {
/* modem latch and XLD 8040 T1 input */
D(printf("XLD 8040 T1:%d loop-back:%d modem+phone:%d offhook(modem relay):%d phaudio:%d DTMF:%d O/!A(originate/answer):%d SQT(squelch transmitter):%d\n",!!(byte&0x80),!!(byte&0x40),!!(byte&0x20),!!(byte&0x10),!!(byte&0x08),!!(byte&0x04),!!(byte&0x02),!!(byte&0x01)));
modem_latch = byte;
}
else if (xld_d_enabled && addr == 0xd110) {
/* XLD byte output from atari to disk latch */
D(printf("d110: disk output byte:%2x\n",byte));
if (modem_latch & 0x80){
/* 8040 T1=1 */
CommandIndex = 0;
DataIndex = 0;
TransferStatus = PIO_CommandFrame;
ExpectedBytes = 5;
D(printf("command frame expected\n"));
}
else if (TransferStatus == PIO_StatusRead || TransferStatus == PIO_ReadFrame) {
D(printf("read ack strobe\n"));
}
else {
PIO_PutByte(byte);
}
}
}
int PBI_XLD_D1ffPutByte(UBYTE byte)
{
int result = 0; /* handled */
if (xld_d_enabled && byte == DISK_MASK) {
memcpy(MEMORY_mem + 0xd800, diskrom, 0x800);
D(printf("DISK rom activated\n"));
}
else if (byte == MODEM_MASK) {
memcpy(MEMORY_mem + 0xd800, voicerom + 0x800, 0x800);
D(printf("MODEM rom activated\n"));
}
else if (byte == VOICE_MASK) {
memcpy(MEMORY_mem + 0xd800, voicerom, 0x800);
D(printf("VOICE rom activated\n"));
}
else result = PBI_NOT_HANDLED;
return result;
}
static void votrax_busy_callback(int busy_status)
{
if (!busy_status && (votrax_latch & 0x80)){
/* busy->idle and IRQ enabled */
D(printf("votrax IRQ generated\n"));
CPU_GenerateIRQ();
PBI_IRQ |= VOICE_MASK;
}
else if (busy_status && (PBI_IRQ & VOICE_MASK)) {
/* idle->busy and PBI_IRQ set */
PBI_IRQ &= ~VOICE_MASK;
/* update pokey IRQ status */
POKEY_PutByte(POKEY_OFFSET_IRQEN, POKEY_IRQEN);
}
}
static void votrax_busy_callback_async(int busy_status)
{
return;
/* do nothing */
}
/* from sio.c */
static UBYTE WriteSectorBack(void)
{
UWORD sector;
UBYTE unit;
sector = CommandFrame[2] + (CommandFrame[3] << 8);
unit = CommandFrame[0] - '1';
if (unit >= SIO_MAX_DRIVES) /* UBYTE range ! */
return 0;
switch (CommandFrame[1]) {
case 0x4f: /* Write Status Block */
return SIO_WriteStatusBlock(unit, DataBuffer);
case 0x50: /* Write */
case 0x57:
case 0xD0: /* xf551 hispeed */
case 0xD7:
return SIO_WriteSector(unit, sector, DataBuffer);
default:
return 'E';
}
}
/* Put a byte that comes from the parallel bus */
static void PIO_PutByte(int byte)
{
D(printf("TransferStatus:%d\n",TransferStatus));
switch (TransferStatus) {
case PIO_CommandFrame:
D(printf("CommandIndex:%d ExpectedBytes:%d\n",CommandIndex,ExpectedBytes));
if (CommandIndex < ExpectedBytes) {
CommandFrame[CommandIndex++] = byte;
if (CommandIndex >= ExpectedBytes) {
if (CommandFrame[0] >= 0x31 && CommandFrame[0] <= 0x38) {
TransferStatus = PIO_StatusRead;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL + ACK_INTERVAL;*/
D(printf("TransferStatus = PIO_StatusRead\n"));
}
else{
TransferStatus = PIO_NoFrame;
D(printf("TransferStatus = PIO_NoFrame\n"));
}
}
}
else {
Log_print("Invalid command frame!");
TransferStatus = PIO_NoFrame;
}
break;
case PIO_WriteFrame: /* Expect data */
if (DataIndex < ExpectedBytes) {
DataBuffer[DataIndex++] = byte;
if (DataIndex >= ExpectedBytes) {
UBYTE sum = SIO_ChkSum(DataBuffer, ExpectedBytes - 1);
if (sum == DataBuffer[ExpectedBytes - 1]) {
UBYTE result = WriteSectorBack();
if (result != 0) {
DataBuffer[0] = 'A';
DataBuffer[1] = result;
DataIndex = 0;
ExpectedBytes = 2;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL + ACK_INTERVAL;*/
TransferStatus = PIO_FinalStatus;
}
else
TransferStatus = PIO_NoFrame;
}
else {
DataBuffer[0] = 'E';
DataIndex = 0;
ExpectedBytes = 1;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL + ACK_INTERVAL;*/
TransferStatus = PIO_FinalStatus;
}
}
}
else {
Log_print("Invalid data frame!");
}
break;
}
/*DELAYED_SEROUT_IRQ = SEROUT_INTERVAL;*/
}
/* Get a byte from the floppy to the parallel bus. */
static int PIO_GetByte(void)
{
int byte = 0;
D(printf("PIO_GetByte TransferStatus:%d\n",TransferStatus));
switch (TransferStatus) {
case PIO_StatusRead:
byte = PIO_Command_Frame(); /* Handle now the command */
break;
case PIO_FormatFrame:
TransferStatus = PIO_ReadFrame;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL << 3;*/
/* FALL THROUGH */
case PIO_ReadFrame:
D(printf("ReadFrame: DataIndex:%d ExpectedBytes:%d\n",DataIndex,ExpectedBytes));
if (DataIndex < ExpectedBytes) {
byte = DataBuffer[DataIndex++];
if (DataIndex >= ExpectedBytes) {
TransferStatus = PIO_NoFrame;
}
/*else {*/
/* set delay using the expected transfer speed */
/*DELAYED_SERIN_IRQ = (DataIndex == 1) ? SERIN_INTERVAL*/
/*: ((SERIN_INTERVAL * AUDF[CHAN3] - 1) / 0x28 + 1);*/
/*}*/
}
else {
Log_print("Invalid read frame!");
TransferStatus = PIO_NoFrame;
}
break;
case PIO_FinalStatus:
if (DataIndex < ExpectedBytes) {
byte = DataBuffer[DataIndex++];
if (DataIndex >= ExpectedBytes) {
TransferStatus = PIO_NoFrame;
}
/*else {
if (DataIndex == 0)
DELAYED_SERIN_IRQ = SERIN_INTERVAL + ACK_INTERVAL;
else
DELAYED_SERIN_IRQ = SERIN_INTERVAL;
}*/
}
else {
Log_print("Invalid read frame!");
TransferStatus = PIO_NoFrame;
}
break;
default:
break;
}
return byte;
}
static UBYTE PIO_Command_Frame(void)
{
int unit;
int sector;
int realsize;
sector = CommandFrame[2] | (((UWORD) CommandFrame[3]) << 8);
unit = CommandFrame[0] - '1';
if (unit < 0 || unit >= SIO_MAX_DRIVES) {
/* Unknown device */
Log_print("Unknown command frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
TransferStatus = PIO_NoFrame;
return 0;
}
switch (CommandFrame[1]) {
case 0x01:
Log_print("PIO DISK: Set large mode (unimplemented)");
return 'E';
case 0x02:
Log_print("PIO DISK: Set small mode (unimplemented)");
return 'E';
case 0x23:
Log_print("PIO DISK: Drive Diagnostic In (unimplemented)");
return 'E';
case 0x24:
Log_print("PIO DISK: Drive Diagnostic Out (unimplemented)");
return 'E';
case 0x4e: /* Read Status */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Read-status frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
DataBuffer[0] = SIO_ReadStatusBlock(unit, DataBuffer + 1);
DataBuffer[13] = SIO_ChkSum(DataBuffer + 1, 12);
DataIndex = 0;
ExpectedBytes = 14;
TransferStatus = PIO_ReadFrame;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL;*/
return 'A';
case 0x4f: /* Write status */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Write-status frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
ExpectedBytes = 13;
DataIndex = 0;
TransferStatus = PIO_WriteFrame;
return 'A';
case 0x50: /* Write */
case 0x57:
#ifdef PBI_DEBUG
Log_print("PIO DISK: Write-sector frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
SIO_SizeOfSector((UBYTE) unit, sector, &realsize, NULL);
ExpectedBytes = realsize + 1;
DataIndex = 0;
TransferStatus = PIO_WriteFrame;
SIO_last_op = SIO_LAST_WRITE;
SIO_last_op_time = 10;
SIO_last_drive = unit + 1;
return 'A';
case 0x52: /* Read */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Read-sector frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
SIO_SizeOfSector((UBYTE) unit, sector, &realsize, NULL);
DataBuffer[0] = SIO_ReadSector(unit, sector, DataBuffer + 1);
DataBuffer[1 + realsize] = SIO_ChkSum(DataBuffer + 1, realsize);
DataIndex = 0;
ExpectedBytes = 2 + realsize;
TransferStatus = PIO_ReadFrame;
/* wait longer before confirmation because bytes could be lost */
/* before the buffer was set (see $E9FB & $EA37 in XL-OS) */
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL << 2;*/
/*
#ifndef NO_SECTOR_DELAY
if (sector == 1) {
//DELAYED_SERIN_IRQ += delay_counter;
delay_counter = SECTOR_DELAY;
}
else {
delay_counter = 0;
}
#endif*/
SIO_last_op = SIO_LAST_READ;
SIO_last_op_time = 10;
SIO_last_drive = unit + 1;
return 'A';
case 0x53: /* Status */
/*
from spec doc:
BYTE 1 - DISK STATUS
BIT 0 = 1 indicates an invalid
command frame was receiv-
ed.
BIT 1 = 1 indicates an invalid
data frame was received.
BIT 2 = 1 indicates an opera-
tion was unsuccessful.
BIT 3 = 1 indicates the disk-
ette is write protected.
BIT 4 = 1 indicates drive is
active.
BITS 5-7 = 100 indicates single
density format.
BITS 5-7 = 101 indicates double
density format.
BYTE 2 - DISK CONTROLLER HARDWARE
STATUS
This byte shall contain the in-
verted value of the disk con-
troller hardware status regis-
ter as of the last operation.
The hardware status value for
no errors shall be $FF. A zero
in any bit position shall indi-
cate an error. The definition
of the bit positions shall be:
BIT 0 = 0 indicates device busy
BIT 1 = 0 indicates data re-
quest is full on a read
operation.
BIT 2 = 0 indicates data lost
BIT 3 = 0 indicates CRC error
BIT 4 = 0 indicates desired
track and sector not found
BIT 5 = 0 indicates record
type/write fault
BIT 6 NOT USED
*BIT 7 = 0 indicates device not
ready (door open)
BYTES 3 & 4 - TIMEOUT
These bytes shall contain a
disk controller provided maxi-
mum timeout value, in seconds,
for the worst case command. The
worst case operation is for a
disk format command (time TBD
seconds). Byte 4 is not used,
currently.*/
/*****Compare with:******/
/*
Status Request from Atari 400/800 Technical Reference Notes
DVSTAT + 0 Command Status
DVSTAT + 1 Hardware Status
DVSTAT + 2 Timeout
DVSTAT + 3 Unused
Command Status Bits
Bit 0 = 1 indicates an invalid command frame was received(same)
Bit 1 = 1 indicates an invalid data frame was received(same)
Bit 2 = 1 indicates that last read/write operation was unsuccessful(same)
Bit 3 = 1 indicates that the diskette is write protected(same)
Bit 4 = 1 indicates active/standby(same)
plus
Bit 5 = 1 indicates double density
Bit 7 = 1 indicates dual density disk (1050 format)
*/
#ifdef PBI_DEBUG
Log_print("PIO DISK: Status frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
/*if (SIO_drive_status[unit]==SIO_OFF) SIO_drive_status[unit]=SIO_NO_DISK;*/
/*need to modify the line below also for SIO_OFF==SIO_NO_DISK*/
DataBuffer[0] = SIO_DriveStatus(unit, DataBuffer + 1);
DataBuffer[2] = 0xff;/*/1;//SIO_DriveStatus(unit, DataBuffer + 1);*/
if (SIO_drive_status[unit]==SIO_NO_DISK || SIO_drive_status[unit]==SIO_OFF){
/*Can't turn 1450XLD drives off, so make SIO_OFF==SIO_NO_DISK*/
DataBuffer[2]=0x7f;
}
DataBuffer[1 + 4] = SIO_ChkSum(DataBuffer + 1, 4);
DataIndex = 0;
ExpectedBytes = 6;
TransferStatus = PIO_ReadFrame;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL;*/
return 'A';
case 0x21: /* Format Disk */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Format-disk frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
realsize = SIO_format_sectorsize[unit];
DataBuffer[0] = SIO_FormatDisk(unit, DataBuffer + 1, realsize, SIO_format_sectorcount[unit]);
DataBuffer[1 + realsize] = SIO_ChkSum(DataBuffer + 1, realsize);
DataIndex = 0;
ExpectedBytes = 2 + realsize;
TransferStatus = PIO_FormatFrame;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL;*/
return 'A';
case 0x22: /* Dual Density Format */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Format-Medium frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
DataBuffer[0] = SIO_FormatDisk(unit, DataBuffer + 1, 128, 1040);
DataBuffer[1 + 128] = SIO_ChkSum(DataBuffer + 1, 128);
DataIndex = 0;
ExpectedBytes = 2 + 128;
TransferStatus = PIO_FormatFrame;
/*DELAYED_SERIN_IRQ = SERIN_INTERVAL;*/
return 'A';
/*
The Integral Disk Drive uses COMMAND BYTE $B1 and
$B2 for internal use. These COMMAND BYTES may not
be used by any other drivers.*/
case 0xb1:
Log_print("PIO DISK: Internal Command 0xb1 (unimplemented)");
return 'E';
case 0xb2:
Log_print("PIO DISK: Internal Command 0xb2 (unimplemented)");
return 'E';
default:
/* Unknown command for a disk drive */
#ifdef PBI_DEBUG
Log_print("PIO DISK: Unknown Command frame: %02x %02x %02x %02x %02x",
CommandFrame[0], CommandFrame[1], CommandFrame[2],
CommandFrame[3], CommandFrame[4]);
#endif
TransferStatus = PIO_NoFrame;
return 'E';
}
}
/* called from POKEYSND_Init */
void PBI_XLD_VInit(int playback_freq, int n_pokeys, int b16)
{
static struct Votrax_interface vi;
int temp_votrax_buffer_size;
bit16 = b16;
dsprate = playback_freq;
num_pokeys = n_pokeys;
if (!xld_v_enabled) return;
if (num_pokeys != 1 && num_pokeys != 2) {
Log_print("PBI_XLD_VInit: cannot handle num_pokeys=%d", num_pokeys);
xld_v_enabled = FALSE;
return;
}
vi.num = 1;
vi.BusyCallback = votrax_busy_callback_async;
Votrax_Stop();
Votrax_Start((void *)&vi);
samples_per_frame = dsprate/(Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60);
ratio = (double)VTRX_RATE/(double)dsprate;
temp_votrax_buffer_size = (int)(VTRX_BLOCK_SIZE*ratio + 10); /* +10 .. little extra? */
free(temp_votrax_buffer);
temp_votrax_buffer = (SWORD *)Util_malloc(temp_votrax_buffer_size*sizeof(SWORD));
free(votrax_buffer);
votrax_buffer = (SWORD *)Util_malloc(VTRX_BLOCK_SIZE*sizeof(SWORD));
}
/* process votrax and interpolate samples */
static void votrax_process(SWORD *v_buffer, int len, SWORD *temp_v_buffer)
{
static SWORD last_sample;
static SWORD last_sample2;
static double startpos;
static int have;
int max_left_sample_index = (int)(startpos + (double)(len - 1)*ratio);
int pos = 0;
double fraction = 0;
int i;
int floor_next_pos;
if (have == 2) {
temp_v_buffer[0] = last_sample;
temp_v_buffer[1] = last_sample2;
Votrax_Update(0, temp_v_buffer + 2, (max_left_sample_index + 1 + 1) - 2);
}
else if (have == 1) {
temp_v_buffer[0] = last_sample;
Votrax_Update(0, temp_v_buffer + 1, (max_left_sample_index + 1 + 1) - 1);
}
else if (have == 0) {
Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1);
}
else if (have < 0) {
Votrax_Update(0, temp_v_buffer, -have);
Votrax_Update(0, temp_v_buffer, max_left_sample_index + 1 + 1);
}
for (i = 0; i < len; i++) {
SWORD left_sample;
SWORD right_sample;
SWORD interp_sample;
pos = (int)(startpos + (double)i*ratio);
fraction = startpos + (double)i*ratio - (double)pos;
left_sample = temp_v_buffer[pos];
right_sample = temp_v_buffer[pos+1];
interp_sample = (int)(left_sample + fraction*(double)(right_sample-left_sample));
v_buffer[i] = interp_sample;
}
floor_next_pos = (int)(startpos + (double)len*ratio);
startpos = (startpos + (double)len*ratio) - (double)floor_next_pos;
if (floor_next_pos == max_left_sample_index)
{
have = 2;
last_sample = temp_v_buffer[floor_next_pos];
last_sample2 = temp_v_buffer[floor_next_pos+1];
}
else if (floor_next_pos == max_left_sample_index + 1) {
have = 1;
last_sample = temp_v_buffer[floor_next_pos];
}
else {
have = (floor_next_pos - (max_left_sample_index + 2));
}
}
/* 16 bit mixing */
static void mix(SWORD *dst, SWORD *src, int sndn, int volume)
{
SWORD s1, s2;
int val;
int channel = 0;
while (sndn--) {
s1 = *src;
s1 = s1*volume/128;
s2 = *dst;
src++;
val = s1 + s2;
if (val > 32767) val = 32767;
if (val < -32768) val = -32768;
*dst++ = val;
if (num_pokeys == 2) {
if (!channel) {
channel = !channel;
sndn++;
src--;
}
}
}
}
/* 8 bit mixing */
static void mix8(UBYTE *dst, SWORD *src, int sndn, int volume)
{
SWORD s1, s2;
int val;
int channel = 0;
while (sndn--) {
s1 = *src;
s1 = s1*volume/128;
s2 = ((int)(*dst) - 0x80)*256;
src++;
val = s1 + s2;
if (val > 32767) val = 32767;
if (val < -32768) val = -32768;
*dst++ = (UBYTE)((val/256) + 0x80);
if (num_pokeys == 2) {
if (!channel) {
channel = !channel;
sndn++;
src--;
}
}
}
}
void PBI_XLD_VFrame(void)
{
if (!xld_v_enabled) return;
votrax_sync_samples -= samples_per_frame;
if (votrax_sync_samples <= 0 ) {
votrax_sync_samples = 0;
votrax_busy = FALSE;
votrax_busy_callback(FALSE); /* busy -> idle */
}
}
void PBI_XLD_VProcess(void *sndbuffer, int sndn)
{
if (!xld_v_enabled) return;
if(votrax_written) {
votrax_written = FALSE;
Votrax_PutByte(votrax_written_byte);
}
while (sndn > 0) {
int amount = ((sndn > VTRX_BLOCK_SIZE) ? VTRX_BLOCK_SIZE : sndn);
votrax_process(votrax_buffer, amount, temp_votrax_buffer);
if (bit16) mix((SWORD *)sndbuffer, votrax_buffer, amount, 128/4);
else mix8((UBYTE *)sndbuffer, votrax_buffer, amount, 128/4);
sndbuffer = (char *) sndbuffer + VTRX_BLOCK_SIZE*(bit16 ? 2 : 1)*((num_pokeys == 2) ? 2: 1);
sndn -= VTRX_BLOCK_SIZE;
}
}
#ifndef BASIC
void PBI_XLD_StateSave(void)
{
StateSav_SaveINT(&PBI_XLD_enabled, 1);
if (PBI_XLD_enabled) {
StateSav_SaveINT(&xld_v_enabled, 1);
StateSav_SaveINT(&xld_d_enabled, 1);
StateSav_SaveFNAME(xld_d_rom_filename);
StateSav_SaveFNAME(xld_v_rom_filename);
StateSav_SaveUBYTE(&votrax_latch, 1);
StateSav_SaveUBYTE(&modem_latch, 1);
StateSav_SaveUBYTE(CommandFrame, sizeof(CommandFrame));
StateSav_SaveINT(&CommandIndex, 1);
StateSav_SaveUBYTE(DataBuffer, sizeof(DataBuffer));
StateSav_SaveINT(&DataIndex, 1);
StateSav_SaveINT(&TransferStatus, 1);
StateSav_SaveINT(&ExpectedBytes, 1);
StateSav_SaveINT(&votrax_busy, 1);
}
}
void PBI_XLD_StateRead(void)
{
StateSav_ReadINT(&PBI_XLD_enabled, 1);
if (PBI_XLD_enabled) {
/* UI should have paused sound while doing this */
StateSav_ReadINT(&xld_v_enabled, 1);
StateSav_ReadINT(&xld_d_enabled, 1);
StateSav_ReadFNAME(xld_d_rom_filename);
StateSav_ReadFNAME(xld_v_rom_filename);
if (xld_v_enabled) {
init_xld_v();
if (dsprate) PBI_XLD_VInit(dsprate, num_pokeys, bit16);
}
if (xld_d_enabled) init_xld_d();
StateSav_ReadUBYTE(&votrax_latch, 1);
StateSav_ReadUBYTE(&modem_latch, 1);
StateSav_ReadUBYTE(CommandFrame, sizeof(CommandFrame));
StateSav_ReadINT(&CommandIndex, 1);
StateSav_ReadUBYTE(DataBuffer, sizeof(DataBuffer));
StateSav_ReadINT(&DataIndex, 1);
StateSav_ReadINT(&TransferStatus, 1);
StateSav_ReadINT(&ExpectedBytes, 1);
StateSav_ReadINT(&votrax_busy, 1);
}
else {
xld_v_enabled = FALSE;
xld_d_enabled = FALSE;
}
}
#endif /* #ifndef BASIC */
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,20 +0,0 @@
#ifndef PBI_XLD_H_
#define PBI_XLD_H_
#include "atari.h"
int PBI_XLD_Initialise(int *argc, char *argv[]);
int PBI_XLD_ReadConfig(char *string, char *ptr);
void PBI_XLD_WriteConfig(FILE *fp);
void PBI_XLD_Reset(void);
int PBI_XLD_D1GetByte(UWORD addr);
UBYTE PBI_XLD_D1ffGetByte(void);
void PBI_XLD_D1PutByte(UWORD addr, UBYTE byte);
int PBI_XLD_D1ffPutByte(UBYTE byte);
extern int PBI_XLD_enabled;
void PBI_XLD_VInit(int playback_freq, int num_pokeys, int bit16);
void PBI_XLD_VFrame(void);
void PBI_XLD_VProcess(void *sndbuffer, int sndn);
void PBI_XLD_StateSave(void);
void PBI_XLD_StateRead(void);
#endif /* PBI_XLD_H_ */

View File

@@ -1,17 +0,0 @@
/* joystick types for DOS port of David Firth's Atari800 emulator */
#define joy_off 0
#define joy_analog 1
#define joy_lpt1 2
#define joy_lpt2 3
#define joy_lpt3 4
#define joy_keyset0 5
#define joy_keyset1 6
#define joy_keyset2 7
#define joy_keyset3 8
#define JOYSTICKTYPES 9
char joyparams[JOYSTICKTYPES][10]={"OFF","PC","LPT1","LPT2",
"LPT3","KEYSET_0","KEYSET_1","KEYSET_2","KEYSET_3"};

View File

@@ -1,222 +0,0 @@
/*
* pia.c - PIA chip emulation
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "atari.h"
#include "cpu.h"
#include "memory.h"
#include "pia.h"
#include "sio.h"
#ifdef XEP80_EMULATION
#include "xep80.h"
#endif
#ifndef BASIC
#include "input.h"
#include "statesav.h"
#endif
UBYTE PIA_PACTL;
UBYTE PIA_PBCTL;
UBYTE PIA_PORTA;
UBYTE PIA_PORTB;
UBYTE PIA_PORT_input[2];
UBYTE PIA_PORTA_mask;
UBYTE PIA_PORTB_mask;
int PIA_Initialise(int *argc, char *argv[])
{
PIA_PACTL = 0x3f;
PIA_PBCTL = 0x3f;
PIA_PORTA = 0xff;
PIA_PORTB = 0xff;
PIA_PORTA_mask = 0xff;
PIA_PORTB_mask = 0xff;
PIA_PORT_input[0] = 0xff;
PIA_PORT_input[1] = 0xff;
return TRUE;
}
void PIA_Reset(void)
{
PIA_PORTA = 0xff;
if (Atari800_machine_type == Atari800_MACHINE_XLXE) {
MEMORY_HandlePORTB(0xff, (UBYTE) (PIA_PORTB | PIA_PORTB_mask));
}
PIA_PORTB = 0xff;
}
UBYTE PIA_GetByte(UWORD addr)
{
switch (addr & 0x03) {
case PIA_OFFSET_PACTL:
return PIA_PACTL & 0x3f;
case PIA_OFFSET_PBCTL:
return PIA_PBCTL & 0x3f;
case PIA_OFFSET_PORTA:
if ((PIA_PACTL & 0x04) == 0) {
/* direction register */
return ~PIA_PORTA_mask;
}
else {
/* port state */
#ifdef XEP80_EMULATION
if (XEP80_enabled) {
return(XEP80_GetBit() & PIA_PORT_input[0] & (PIA_PORTA | PIA_PORTA_mask));
}
#endif /* XEP80_EMULATION */
return PIA_PORT_input[0] & (PIA_PORTA | PIA_PORTA_mask);
}
case PIA_OFFSET_PORTB:
if ((PIA_PBCTL & 0x04) == 0) {
/* direction register */
return ~PIA_PORTB_mask;
}
else {
/* port state */
if (Atari800_machine_type == Atari800_MACHINE_XLXE) {
return PIA_PORTB | PIA_PORTB_mask;
}
else {
return PIA_PORT_input[1] & (PIA_PORTB | PIA_PORTB_mask);
}
}
}
/* for stupid compilers */
return 0xff;
}
void PIA_PutByte(UWORD addr, UBYTE byte)
{
switch (addr & 0x03) {
case PIA_OFFSET_PACTL:
/* This code is part of the cassette emulation */
/* The motor status has changed */
SIO_TapeMotor(byte & 0x08 ? 0 : 1);
PIA_PACTL = byte;
break;
case PIA_OFFSET_PBCTL:
/* This code is part of the serial I/O emulation */
if ((PIA_PBCTL ^ byte) & 0x08) {
/* The command line status has changed */
SIO_SwitchCommandFrame(byte & 0x08 ? 0 : 1);
}
PIA_PBCTL = byte;
break;
case PIA_OFFSET_PORTA:
if ((PIA_PACTL & 0x04) == 0) {
/* set direction register */
PIA_PORTA_mask = ~byte;
}
else {
/* set output register */
#ifdef XEP80_EMULATION
if (XEP80_enabled && (~PIA_PORTA_mask & 0x11)) {
XEP80_PutBit(byte);
}
#endif /* XEP80_EMULATION */
PIA_PORTA = byte; /* change from thor */
}
#ifndef BASIC
INPUT_SelectMultiJoy((PIA_PORTA | PIA_PORTA_mask) >> 4);
#endif
break;
case PIA_OFFSET_PORTB:
if (Atari800_machine_type == Atari800_MACHINE_XLXE) {
if ((PIA_PBCTL & 0x04) == 0) {
/* direction register */
MEMORY_HandlePORTB((UBYTE) (PIA_PORTB | ~byte), (UBYTE) (PIA_PORTB | PIA_PORTB_mask));
PIA_PORTB_mask = ~byte;
}
else {
/* output register */
MEMORY_HandlePORTB((UBYTE) (byte | PIA_PORTB_mask), (UBYTE) (PIA_PORTB | PIA_PORTB_mask));
PIA_PORTB = byte;
}
}
else {
if ((PIA_PBCTL & 0x04) == 0) {
/* direction register */
PIA_PORTB_mask = ~byte;
}
else {
/* output register */
PIA_PORTB = byte;
}
}
break;
}
}
#ifndef BASIC
void PIA_StateSave(void)
{
int Ram256 = 0;
if (MEMORY_ram_size == MEMORY_RAM_320_RAMBO)
Ram256 = 1;
else if (MEMORY_ram_size == MEMORY_RAM_320_COMPY_SHOP)
Ram256 = 2;
StateSav_SaveUBYTE( &PIA_PACTL, 1 );
StateSav_SaveUBYTE( &PIA_PBCTL, 1 );
StateSav_SaveUBYTE( &PIA_PORTA, 1 );
StateSav_SaveUBYTE( &PIA_PORTB, 1 );
StateSav_SaveINT( &MEMORY_xe_bank, 1 );
StateSav_SaveINT( &MEMORY_selftest_enabled, 1 );
StateSav_SaveINT( &Ram256, 1 );
StateSav_SaveINT( &MEMORY_cartA0BF_enabled, 1 );
StateSav_SaveUBYTE( &PIA_PORTA_mask, 1 );
StateSav_SaveUBYTE( &PIA_PORTB_mask, 1 );
}
void PIA_StateRead(void)
{
int Ram256 = 0;
StateSav_ReadUBYTE( &PIA_PACTL, 1 );
StateSav_ReadUBYTE( &PIA_PBCTL, 1 );
StateSav_ReadUBYTE( &PIA_PORTA, 1 );
StateSav_ReadUBYTE( &PIA_PORTB, 1 );
StateSav_ReadINT( &MEMORY_xe_bank, 1 );
StateSav_ReadINT( &MEMORY_selftest_enabled, 1 );
StateSav_ReadINT( &Ram256, 1 );
if (Ram256 == 1 && Atari800_machine_type == Atari800_MACHINE_XLXE && MEMORY_ram_size == MEMORY_RAM_320_COMPY_SHOP)
MEMORY_ram_size = MEMORY_RAM_320_RAMBO;
StateSav_ReadINT( &MEMORY_cartA0BF_enabled, 1 );
StateSav_ReadUBYTE( &PIA_PORTA_mask, 1 );
StateSav_ReadUBYTE( &PIA_PORTB_mask, 1 );
}
#endif /* BASIC */

View File

@@ -1,26 +0,0 @@
#ifndef PIA_H_
#define PIA_H_
#include "atari.h"
#define PIA_OFFSET_PORTA 0x00
#define PIA_OFFSET_PORTB 0x01
#define PIA_OFFSET_PACTL 0x02
#define PIA_OFFSET_PBCTL 0x03
extern UBYTE PIA_PACTL;
extern UBYTE PIA_PBCTL;
extern UBYTE PIA_PORTA;
extern UBYTE PIA_PORTB;
extern UBYTE PIA_PORTA_mask;
extern UBYTE PIA_PORTB_mask;
extern UBYTE PIA_PORT_input[2];
int PIA_Initialise(int *argc, char *argv[]);
void PIA_Reset(void);
UBYTE PIA_GetByte(UWORD addr);
void PIA_PutByte(UWORD addr, UBYTE byte);
void PIA_StateSave(void);
void PIA_StateRead(void);
#endif /* PIA_H_ */

View File

@@ -1,75 +0,0 @@
#ifndef PLATFORM_H_
#define PLATFORM_H_
#include "config.h"
#include <stdio.h>
/* This include file defines prototypes for platform-specific functions. */
int PLATFORM_Initialise(int *argc, char *argv[]);
int PLATFORM_Exit(int run_monitor);
int PLATFORM_Keyboard(void);
void PLATFORM_DisplayScreen(void);
int PLATFORM_PORT(int num);
int PLATFORM_TRIG(int num);
#ifdef SUPPORTS_PLATFORM_CONFIGINIT
/* This function sets the configuration parameters to default values */
void PLATFORM_ConfigInit(void);
#endif
#ifdef SUPPORTS_PLATFORM_CONFIGURE
/* This procedure processes lines not recognized by RtConfigLoad. */
int PLATFORM_Configure(char *option, char *parameters);
#endif
#ifdef SUPPORTS_PLATFORM_CONFIGSAVE
/* This function saves additional config lines */
void PLATFORM_ConfigSave(FILE *fp);
#endif
#ifdef SUPPORTS_PLATFORM_PALETTEUPDATE
/* This function updates the palette */
/* If the platform does a conversion of colortable when it initialises
* and the user changes colortable (such as changing from PAL to NTSC)
* then this function should update the platform palette */
void PLATFORM_PaletteUpdate(void);
#endif
#ifdef SUPPORTS_PLATFORM_SLEEP
/* This function is for those ports that need their own version of sleep */
void PLATFORM_Sleep(double s);
#endif
#ifdef SDL
/* used in UI to show how the keyboard joystick is mapped */
extern int PLATFORM_kbd_joy_0_enabled;
extern int PLATFORM_kbd_joy_1_enabled;
int PLATFORM_GetRawKey(void);
#endif
#ifdef XEP80_EMULATION
/* Switch between the Atari and XEP80 screen */
void PLATFORM_SwitchXep80(void);
/* TRUE if the XEP80 screen is visible */
extern int PLATFORM_xep80;
#endif
#ifdef NTSC_FILTER
enum PLATFORM_filter_t {
PLATFORM_FILTER_NONE,
PLATFORM_FILTER_NTSC
};
/* Represents whether the NTSC filter is turned on. Don't set this value
directly. */
extern enum PLATFORM_filter_t PLATFORM_filter;
/* This function turns the NTSC filter on or off. Changing the
PLATFORM_filter variable directly is not allowed; use this function
instead. */
void PLATFORM_SetFilter(const enum PLATFORM_filter_t filter);
#endif /* NTSC_FILTER */
#endif /* PLATFORM_H_ */

View File

@@ -1,667 +0,0 @@
/*
* pokey.c - POKEY sound chip emulation
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include "atari.h"
#include "cpu.h"
#include "esc.h"
#include "pia.h"
#include "pokey.h"
#include "gtia.h"
#include "sio.h"
#ifndef BASIC
#include "input.h"
#include "statesav.h"
#endif
#ifdef SOUND
#include "pokeysnd.h"
#endif
#include "antic.h"
#include "cassette.h"
#include "log.h"
#include "input.h"
#include "pbi.h"
#ifdef POKEY_UPDATE
void pokey_update(void);
#endif
UBYTE POKEY_KBCODE;
UBYTE POKEY_SERIN;
UBYTE POKEY_IRQST;
UBYTE POKEY_IRQEN;
UBYTE POKEY_SKSTAT;
UBYTE POKEY_SKCTL;
int POKEY_DELAYED_SERIN_IRQ;
int POKEY_DELAYED_SEROUT_IRQ;
int POKEY_DELAYED_XMTDONE_IRQ;
/* structures to hold the 9 pokey control bytes */
UBYTE POKEY_AUDF[4 * POKEY_MAXPOKEYS]; /* AUDFx (D200, D202, D204, D206) */
UBYTE POKEY_AUDC[4 * POKEY_MAXPOKEYS]; /* AUDCx (D201, D203, D205, D207) */
UBYTE POKEY_AUDCTL[POKEY_MAXPOKEYS]; /* AUDCTL (D208) */
int POKEY_DivNIRQ[4], POKEY_DivNMax[4];
int POKEY_Base_mult[POKEY_MAXPOKEYS]; /* selects either 64Khz or 15Khz clock mult */
UBYTE POKEY_POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228};
static int pot_scanline;
UBYTE POKEY_poly9_lookup[511];
UBYTE POKEY_poly17_lookup[16385];
static ULONG random_scanline_counter;
ULONG POKEY_GetRandomCounter(void)
{
return random_scanline_counter;
}
void POKEY_SetRandomCounter(ULONG value)
{
random_scanline_counter = value;
}
UBYTE POKEY_GetByte(UWORD addr)
{
UBYTE byte = 0xff;
#ifdef STEREO_SOUND
if (addr & 0x0010 && POKEYSND_stereo_enabled)
return 0;
#endif
addr &= 0x0f;
if (addr < 8) {
byte = POKEY_POT_input[addr];
if (byte <= pot_scanline)
return byte;
return pot_scanline;
}
switch (addr) {
case POKEY_OFFSET_ALLPOT:
{
int i;
for (i = 0; i < 8; i++)
if (POKEY_POT_input[i] <= pot_scanline)
byte &= ~(1 << i); /* reset bit if pot value known */
}
break;
case POKEY_OFFSET_KBCODE:
byte = POKEY_KBCODE;
break;
case POKEY_OFFSET_RANDOM:
if ((POKEY_SKCTL & 0x03) != 0) {
int i = random_scanline_counter + ANTIC_XPOS;
if (POKEY_AUDCTL[0] & POKEY_POLY9)
byte = POKEY_poly9_lookup[i % POKEY_POLY9_SIZE];
else {
const UBYTE *ptr;
i %= POKEY_POLY17_SIZE;
ptr = POKEY_poly17_lookup + (i >> 3);
i &= 7;
byte = (UBYTE) ((ptr[0] >> i) + (ptr[1] << (8 - i)));
}
}
break;
case POKEY_OFFSET_SERIN:
byte = POKEY_SERIN;
#ifdef DEBUG3
printf("SERIO: SERIN read, bytevalue %02x\n", POKEY_SERIN);
#endif
#ifdef SERIO_SOUND
POKEYSND_UpdateSerio(0,byte);
#endif
break;
case POKEY_OFFSET_IRQST:
byte = POKEY_IRQST;
break;
case POKEY_OFFSET_SKSTAT:
byte = POKEY_SKSTAT + (CASSETTE_IOLineStatus() << 4);
break;
}
return byte;
}
static void Update_Counter(int chan_mask);
static int POKEY_siocheck(void)
{
return (((POKEY_AUDF[POKEY_CHAN3] == 0x28 || POKEY_AUDF[POKEY_CHAN3] == 0x10
|| POKEY_AUDF[POKEY_CHAN3] == 0x08 || POKEY_AUDF[POKEY_CHAN3] == 0x0a)
&& POKEY_AUDF[POKEY_CHAN4] == 0x00) /* intelligent peripherals speeds */
|| (POKEY_SKCTL & 0x78) == 0x28) /* cassette save mode */
&& (POKEY_AUDCTL[0] & 0x28) == 0x28;
}
#ifndef SOUND_GAIN /* sound gain can be pre-defined in the configure/Makefile */
#define SOUND_GAIN 4
#endif
#ifndef SOUND
#define POKEYSND_Update(addr, val, chip, gain)
#endif
void POKEY_PutByte(UWORD addr, UBYTE byte)
{
#ifdef STEREO_SOUND
addr &= POKEYSND_stereo_enabled ? 0x1f : 0x0f;
#else
addr &= 0x0f;
#endif
switch (addr) {
case POKEY_OFFSET_AUDC1:
POKEY_AUDC[POKEY_CHAN1] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC1, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC2:
POKEY_AUDC[POKEY_CHAN2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC2, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC3:
POKEY_AUDC[POKEY_CHAN3] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC3, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC4:
POKEY_AUDC[POKEY_CHAN4] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC4, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDCTL:
POKEY_AUDCTL[0] = byte;
/* determine the base multiplier for the 'div by n' calculations */
if (byte & POKEY_CLOCK_15)
POKEY_Base_mult[0] = POKEY_DIV_15;
else
POKEY_Base_mult[0] = POKEY_DIV_64;
Update_Counter((1 << POKEY_CHAN1) | (1 << POKEY_CHAN2) | (1 << POKEY_CHAN3) | (1 << POKEY_CHAN4));
POKEYSND_Update(POKEY_OFFSET_AUDCTL, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF1:
POKEY_AUDF[POKEY_CHAN1] = byte;
Update_Counter((POKEY_AUDCTL[0] & POKEY_CH1_CH2) ? ((1 << POKEY_CHAN2) | (1 << POKEY_CHAN1)) : (1 << POKEY_CHAN1));
POKEYSND_Update(POKEY_OFFSET_AUDF1, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF2:
POKEY_AUDF[POKEY_CHAN2] = byte;
Update_Counter(1 << POKEY_CHAN2);
POKEYSND_Update(POKEY_OFFSET_AUDF2, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF3:
POKEY_AUDF[POKEY_CHAN3] = byte;
Update_Counter((POKEY_AUDCTL[0] & POKEY_CH3_CH4) ? ((1 << POKEY_CHAN4) | (1 << POKEY_CHAN3)) : (1 << POKEY_CHAN3));
POKEYSND_Update(POKEY_OFFSET_AUDF3, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF4:
POKEY_AUDF[POKEY_CHAN4] = byte;
Update_Counter(1 << POKEY_CHAN4);
POKEYSND_Update(POKEY_OFFSET_AUDF4, byte, 0, SOUND_GAIN);
break;
case POKEY_OFFSET_IRQEN:
POKEY_IRQEN = byte;
#ifdef DEBUG1
printf("WR: IRQEN = %x, PC = %x\n", POKEY_IRQEN, PC);
#endif
POKEY_IRQST |= ~byte & 0xf7; /* Reset disabled IRQs except XMTDONE */
if (POKEY_IRQEN & 0x20) {
SLONG delay;
delay = CASSETTE_GetInputIRQDelay();
if (delay > 0)
POKEY_DELAYED_SERIN_IRQ = delay;
}
if ((~POKEY_IRQST & POKEY_IRQEN) == 0 && PBI_IRQ == 0)
CPU_IRQ = 0;
else
CPU_GenerateIRQ();
break;
case POKEY_OFFSET_SKRES:
POKEY_SKSTAT |= 0xe0;
break;
case POKEY_OFFSET_POTGO:
if (!(POKEY_SKCTL & 4))
pot_scanline = 0; /* slow pot mode */
break;
case POKEY_OFFSET_SEROUT:
if ((POKEY_SKCTL & 0x70) == 0x20 && POKEY_siocheck())
SIO_PutByte(byte);
/* check if cassette 2-tone mode has been enabled */
if ((POKEY_SKCTL & 0x08) == 0x00) {
/* intelligent device */
POKEY_DELAYED_SEROUT_IRQ = SIO_SEROUT_INTERVAL;
POKEY_IRQST |= 0x08;
POKEY_DELAYED_XMTDONE_IRQ = SIO_XMTDONE_INTERVAL;
}
else {
/* cassette */
/* some savers patch the cassette baud rate, so we evaluate it here */
/* scanlines per second*10 bit*audiofrequency/(1.79 MHz/2) */
POKEY_DELAYED_SEROUT_IRQ = 312*50*10*(POKEY_AUDF[POKEY_CHAN3] + POKEY_AUDF[POKEY_CHAN4]*0x100)/895000;
/* safety check */
if (POKEY_DELAYED_SEROUT_IRQ >= 3) {
POKEY_IRQST |= 0x08;
POKEY_DELAYED_XMTDONE_IRQ = 2*POKEY_DELAYED_SEROUT_IRQ - 2;
}
else {
POKEY_DELAYED_SEROUT_IRQ = 0;
POKEY_DELAYED_XMTDONE_IRQ = 0;
}
};
#ifdef SERIO_SOUND
POKEYSND_UpdateSerio(1, byte);
#endif
break;
case POKEY_OFFSET_STIMER:
POKEY_DivNIRQ[POKEY_CHAN1] = POKEY_DivNMax[POKEY_CHAN1];
POKEY_DivNIRQ[POKEY_CHAN2] = POKEY_DivNMax[POKEY_CHAN2];
POKEY_DivNIRQ[POKEY_CHAN4] = POKEY_DivNMax[POKEY_CHAN4];
POKEYSND_Update(POKEY_OFFSET_STIMER, byte, 0, SOUND_GAIN);
#ifdef DEBUG1
printf("WR: STIMER = %x\n", byte);
#endif
break;
case POKEY_OFFSET_SKCTL:
POKEY_SKCTL = byte;
POKEYSND_Update(POKEY_OFFSET_SKCTL, byte, 0, SOUND_GAIN);
if (byte & 4)
pot_scanline = 228; /* fast pot mode - return results immediately */
break;
#ifdef STEREO_SOUND
case POKEY_OFFSET_AUDC1 + POKEY_OFFSET_POKEY2:
POKEY_AUDC[POKEY_CHAN1 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC1, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC2 + POKEY_OFFSET_POKEY2:
POKEY_AUDC[POKEY_CHAN2 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC2, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC3 + POKEY_OFFSET_POKEY2:
POKEY_AUDC[POKEY_CHAN3 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC3, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDC4 + POKEY_OFFSET_POKEY2:
POKEY_AUDC[POKEY_CHAN4 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDC4, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDCTL + POKEY_OFFSET_POKEY2:
POKEY_AUDCTL[1] = byte;
/* determine the base multiplier for the 'div by n' calculations */
if (byte & POKEY_CLOCK_15)
POKEY_Base_mult[1] = POKEY_DIV_15;
else
POKEY_Base_mult[1] = POKEY_DIV_64;
POKEYSND_Update(POKEY_OFFSET_AUDCTL, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF1 + POKEY_OFFSET_POKEY2:
POKEY_AUDF[POKEY_CHAN1 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDF1, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF2 + POKEY_OFFSET_POKEY2:
POKEY_AUDF[POKEY_CHAN2 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDF2, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF3 + POKEY_OFFSET_POKEY2:
POKEY_AUDF[POKEY_CHAN3 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDF3, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_AUDF4 + POKEY_OFFSET_POKEY2:
POKEY_AUDF[POKEY_CHAN4 + POKEY_CHIP2] = byte;
POKEYSND_Update(POKEY_OFFSET_AUDF4, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_STIMER + POKEY_OFFSET_POKEY2:
POKEYSND_Update(POKEY_OFFSET_STIMER, byte, 1, SOUND_GAIN);
break;
case POKEY_OFFSET_SKCTL + POKEY_OFFSET_POKEY2:
POKEYSND_Update(POKEY_OFFSET_SKCTL, byte, 1, SOUND_GAIN);
break;
#endif
}
}
int POKEY_Initialise(int *argc, char *argv[])
{
int i;
ULONG reg;
/* Initialise Serial Port Interrupts */
POKEY_DELAYED_SERIN_IRQ = 0;
POKEY_DELAYED_SEROUT_IRQ = 0;
POKEY_DELAYED_XMTDONE_IRQ = 0;
POKEY_KBCODE = 0xff;
POKEY_SERIN = 0x00; /* or 0xff ? */
POKEY_IRQST = 0xff;
POKEY_IRQEN = 0x00;
POKEY_SKSTAT = 0xef;
POKEY_SKCTL = 0x00;
for (i = 0; i < (POKEY_MAXPOKEYS * 4); i++) {
POKEY_AUDC[i] = 0;
POKEY_AUDF[i] = 0;
}
for (i = 0; i < POKEY_MAXPOKEYS; i++) {
POKEY_AUDCTL[i] = 0;
POKEY_Base_mult[i] = POKEY_DIV_64;
}
for (i = 0; i < 4; i++)
POKEY_DivNIRQ[i] = POKEY_DivNMax[i] = 0;
pot_scanline = 0;
/* initialise poly9_lookup */
reg = 0x1ff;
for (i = 0; i < 511; i++) {
reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1);
POKEY_poly9_lookup[i] = (UBYTE) reg;
}
/* initialise poly17_lookup */
reg = 0x1ffff;
for (i = 0; i < 16385; i++) {
reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8);
POKEY_poly17_lookup[i] = (UBYTE) (reg >> 1);
}
#ifndef BASIC
if (INPUT_Playingback()) {
random_scanline_counter = INPUT_PlaybackInt();
}
else
#endif
{
random_scanline_counter =
#ifdef WIN32
GetTickCount() % POKEY_POLY17_SIZE;
#elif defined(HAVE_TIME)
time(NULL) % POKEY_POLY17_SIZE;
#else
0;
#endif
}
#ifndef BASIC
if (INPUT_Recording()) {
INPUT_RecordInt(random_scanline_counter);
}
#endif
return TRUE;
}
void POKEY_Frame(void)
{
random_scanline_counter %= (POKEY_AUDCTL[0] & POKEY_POLY9) ? POKEY_POLY9_SIZE : POKEY_POLY17_SIZE;
}
/***************************************************************************
** Generate POKEY Timer IRQs if required **
** called on a per-scanline basis, not very precise, but good enough **
** for most applications **
***************************************************************************/
void POKEY_Scanline(void)
{
#ifdef POKEY_UPDATE
pokey_update();
#endif
#ifdef VOL_ONLY_SOUND
POKEYSND_UpdateVolOnly();
#endif
#ifndef BASIC
INPUT_Scanline(); /* Handle Amiga and ST mice. */
/* It's not a part of POKEY emulation, */
/* but it looks to be the best place to put it. */
#endif
if (pot_scanline < 228)
pot_scanline++;
random_scanline_counter += ANTIC_LINE_C;
/* on nonpatched i/o-operation, enable the cassette timing */
if (!ESC_enable_sio_patch)
CASSETTE_AddScanLine();
if (POKEY_DELAYED_SERIN_IRQ > 0) {
if (--POKEY_DELAYED_SERIN_IRQ == 0) {
if (POKEY_IRQEN & 0x20) {
if (POKEY_IRQST & 0x20) {
POKEY_IRQST &= 0xdf;
POKEY_SERIN = SIO_GetByte();
#ifdef DEBUG2
printf("SERIO: SERIN Interrupt triggered, bytevalue %02x\n", POKEY_SERIN);
#endif
}
else {
POKEY_SKSTAT &= 0xdf;
#ifdef DEBUG2
printf("SERIO: SERIN Interrupt triggered\n");
#endif
}
CPU_GenerateIRQ();
}
#ifdef DEBUG2
else {
printf("SERIO: SERIN Interrupt missed\n");
}
#endif
}
}
if (POKEY_DELAYED_SEROUT_IRQ > 0) {
if (--POKEY_DELAYED_SEROUT_IRQ == 0) {
if (POKEY_IRQEN & 0x10) {
#ifdef DEBUG2
printf("SERIO: SEROUT Interrupt triggered\n");
#endif
POKEY_IRQST &= 0xef;
CPU_GenerateIRQ();
}
#ifdef DEBUG2
else {
printf("SERIO: SEROUT Interrupt missed\n");
}
#endif
}
}
if (POKEY_DELAYED_XMTDONE_IRQ > 0)
if (--POKEY_DELAYED_XMTDONE_IRQ == 0) {
POKEY_IRQST &= 0xf7;
if (POKEY_IRQEN & 0x08) {
#ifdef DEBUG2
printf("SERIO: XMTDONE Interrupt triggered\n");
#endif
CPU_GenerateIRQ();
}
#ifdef DEBUG2
else
printf("SERIO: XMTDONE Interrupt missed\n");
#endif
}
if ((POKEY_DivNIRQ[POKEY_CHAN1] -= ANTIC_LINE_C) < 0 ) {
POKEY_DivNIRQ[POKEY_CHAN1] += POKEY_DivNMax[POKEY_CHAN1];
if (POKEY_IRQEN & 0x01) {
POKEY_IRQST &= 0xfe;
CPU_GenerateIRQ();
}
}
if ((POKEY_DivNIRQ[POKEY_CHAN2] -= ANTIC_LINE_C) < 0 ) {
POKEY_DivNIRQ[POKEY_CHAN2] += POKEY_DivNMax[POKEY_CHAN2];
if (POKEY_IRQEN & 0x02) {
POKEY_IRQST &= 0xfd;
CPU_GenerateIRQ();
}
}
if ((POKEY_DivNIRQ[POKEY_CHAN4] -= ANTIC_LINE_C) < 0 ) {
POKEY_DivNIRQ[POKEY_CHAN4] += POKEY_DivNMax[POKEY_CHAN4];
if (POKEY_IRQEN & 0x04) {
POKEY_IRQST &= 0xfb;
CPU_GenerateIRQ();
}
}
}
/*****************************************************************************/
/* Module: Update_Counter() */
/* Purpose: To process the latest control values stored in the AUDF, AUDC, */
/* and AUDCTL registers. It pre-calculates as much information as */
/* possible for better performance. This routine has been added */
/* here again as I need the precise frequency for the pokey timers */
/* again. The pokey emulation is therefore somewhat sub-optimal */
/* since the actual pokey emulation should grab the frequency values */
/* directly from here instead of calculating them again. */
/* */
/* Author: Ron Fries,Thomas Richter */
/* Date: March 27, 1998 */
/* */
/* Inputs: chan_mask: Channel mask, one bit per channel. */
/* The channels that need to be updated */
/* */
/* Outputs: Adjusts local globals - no return value */
/* */
/*****************************************************************************/
static void Update_Counter(int chan_mask)
{
/************************************************************/
/* As defined in the manual, the exact Div_n_cnt values are */
/* different depending on the frequency and resolution: */
/* 64 kHz or 15 kHz - AUDF + 1 */
/* 1 MHz, 8-bit - AUDF + 4 */
/* 1 MHz, 16-bit - AUDF[CHAN1]+256*AUDF[CHAN2] + 7 */
/************************************************************/
/* only reset the channels that have changed */
if (chan_mask & (1 << POKEY_CHAN1)) {
/* process channel 1 frequency */
if (POKEY_AUDCTL[0] & POKEY_CH1_179)
POKEY_DivNMax[POKEY_CHAN1] = POKEY_AUDF[POKEY_CHAN1] + 4;
else
POKEY_DivNMax[POKEY_CHAN1] = (POKEY_AUDF[POKEY_CHAN1] + 1) * POKEY_Base_mult[0];
if (POKEY_DivNMax[POKEY_CHAN1] < ANTIC_LINE_C)
POKEY_DivNMax[POKEY_CHAN1] = ANTIC_LINE_C;
}
if (chan_mask & (1 << POKEY_CHAN2)) {
/* process channel 2 frequency */
if (POKEY_AUDCTL[0] & POKEY_CH1_CH2) {
if (POKEY_AUDCTL[0] & POKEY_CH1_179)
POKEY_DivNMax[POKEY_CHAN2] = POKEY_AUDF[POKEY_CHAN2] * 256 + POKEY_AUDF[POKEY_CHAN1] + 7;
else
POKEY_DivNMax[POKEY_CHAN2] = (POKEY_AUDF[POKEY_CHAN2] * 256 + POKEY_AUDF[POKEY_CHAN1] + 1) * POKEY_Base_mult[0];
}
else
POKEY_DivNMax[POKEY_CHAN2] = (POKEY_AUDF[POKEY_CHAN2] + 1) * POKEY_Base_mult[0];
if (POKEY_DivNMax[POKEY_CHAN2] < ANTIC_LINE_C)
POKEY_DivNMax[POKEY_CHAN2] = ANTIC_LINE_C;
}
if (chan_mask & (1 << POKEY_CHAN4)) {
/* process channel 4 frequency */
if (POKEY_AUDCTL[0] & POKEY_CH3_CH4) {
if (POKEY_AUDCTL[0] & POKEY_CH3_179)
POKEY_DivNMax[POKEY_CHAN4] = POKEY_AUDF[POKEY_CHAN4] * 256 + POKEY_AUDF[POKEY_CHAN3] + 7;
else
POKEY_DivNMax[POKEY_CHAN4] = (POKEY_AUDF[POKEY_CHAN4] * 256 + POKEY_AUDF[POKEY_CHAN3] + 1) * POKEY_Base_mult[0];
}
else
POKEY_DivNMax[POKEY_CHAN4] = (POKEY_AUDF[POKEY_CHAN4] + 1) * POKEY_Base_mult[0];
if (POKEY_DivNMax[POKEY_CHAN4] < ANTIC_LINE_C)
POKEY_DivNMax[POKEY_CHAN4] = ANTIC_LINE_C;
}
}
#ifndef BASIC
void POKEY_StateSave(void)
{
int shift_key = 0;
int keypressed = 0;
StateSav_SaveUBYTE(&POKEY_KBCODE, 1);
StateSav_SaveUBYTE(&POKEY_IRQST, 1);
StateSav_SaveUBYTE(&POKEY_IRQEN, 1);
StateSav_SaveUBYTE(&POKEY_SKCTL, 1);
StateSav_SaveINT(&shift_key, 1);
StateSav_SaveINT(&keypressed, 1);
StateSav_SaveINT(&POKEY_DELAYED_SERIN_IRQ, 1);
StateSav_SaveINT(&POKEY_DELAYED_SEROUT_IRQ, 1);
StateSav_SaveINT(&POKEY_DELAYED_XMTDONE_IRQ, 1);
StateSav_SaveUBYTE(&POKEY_AUDF[0], 4);
StateSav_SaveUBYTE(&POKEY_AUDC[0], 4);
StateSav_SaveUBYTE(&POKEY_AUDCTL[0], 1);
StateSav_SaveINT(&POKEY_DivNIRQ[0], 4);
StateSav_SaveINT(&POKEY_DivNMax[0], 4);
StateSav_SaveINT(&POKEY_Base_mult[0], 1);
}
void POKEY_StateRead(void)
{
int i;
int shift_key;
int keypressed;
StateSav_ReadUBYTE(&POKEY_KBCODE, 1);
StateSav_ReadUBYTE(&POKEY_IRQST, 1);
StateSav_ReadUBYTE(&POKEY_IRQEN, 1);
StateSav_ReadUBYTE(&POKEY_SKCTL, 1);
StateSav_ReadINT(&shift_key, 1);
StateSav_ReadINT(&keypressed, 1);
StateSav_ReadINT(&POKEY_DELAYED_SERIN_IRQ, 1);
StateSav_ReadINT(&POKEY_DELAYED_SEROUT_IRQ, 1);
StateSav_ReadINT(&POKEY_DELAYED_XMTDONE_IRQ, 1);
StateSav_ReadUBYTE(&POKEY_AUDF[0], 4);
StateSav_ReadUBYTE(&POKEY_AUDC[0], 4);
StateSav_ReadUBYTE(&POKEY_AUDCTL[0], 1);
for (i = 0; i < 4; i++) {
POKEY_PutByte((UWORD) (POKEY_OFFSET_AUDF1 + i * 2), POKEY_AUDF[i]);
POKEY_PutByte((UWORD) (POKEY_OFFSET_AUDC1 + i * 2), POKEY_AUDC[i]);
}
POKEY_PutByte(POKEY_OFFSET_AUDCTL, POKEY_AUDCTL[0]);
StateSav_ReadINT(&POKEY_DivNIRQ[0], 4);
StateSav_ReadINT(&POKEY_DivNMax[0], 4);
StateSav_ReadINT(&POKEY_Base_mult[0], 1);
}
#endif

View File

@@ -1,122 +0,0 @@
#ifndef POKEY_H_
#define POKEY_H_
#ifdef ASAP /* external project, see http://asap.sf.net */
#include "asap_internal.h"
#else
#include "atari.h"
#endif
#define POKEY_OFFSET_AUDF1 0x00
#define POKEY_OFFSET_AUDC1 0x01
#define POKEY_OFFSET_AUDF2 0x02
#define POKEY_OFFSET_AUDC2 0x03
#define POKEY_OFFSET_AUDF3 0x04
#define POKEY_OFFSET_AUDC3 0x05
#define POKEY_OFFSET_AUDF4 0x06
#define POKEY_OFFSET_AUDC4 0x07
#define POKEY_OFFSET_AUDCTL 0x08
#define POKEY_OFFSET_STIMER 0x09
#define POKEY_OFFSET_SKRES 0x0a
#define POKEY_OFFSET_POTGO 0x0b
#define POKEY_OFFSET_SEROUT 0x0d
#define POKEY_OFFSET_IRQEN 0x0e
#define POKEY_OFFSET_SKCTL 0x0f
#define POKEY_OFFSET_POT0 0x00
#define POKEY_OFFSET_POT1 0x01
#define POKEY_OFFSET_POT2 0x02
#define POKEY_OFFSET_POT3 0x03
#define POKEY_OFFSET_POT4 0x04
#define POKEY_OFFSET_POT5 0x05
#define POKEY_OFFSET_POT6 0x06
#define POKEY_OFFSET_POT7 0x07
#define POKEY_OFFSET_ALLPOT 0x08
#define POKEY_OFFSET_KBCODE 0x09
#define POKEY_OFFSET_RANDOM 0x0a
#define POKEY_OFFSET_SERIN 0x0d
#define POKEY_OFFSET_IRQST 0x0e
#define POKEY_OFFSET_SKSTAT 0x0f
#define POKEY_OFFSET_POKEY2 0x10 /* offset to second pokey chip (STEREO expansion) */
#ifndef ASAP
extern UBYTE POKEY_KBCODE;
extern UBYTE POKEY_IRQST;
extern UBYTE POKEY_IRQEN;
extern UBYTE POKEY_SKSTAT;
extern UBYTE POKEY_SKCTL;
extern int POKEY_DELAYED_SERIN_IRQ;
extern int POKEY_DELAYED_SEROUT_IRQ;
extern int POKEY_DELAYED_XMTDONE_IRQ;
extern UBYTE POKEY_POT_input[8];
ULONG POKEY_GetRandomCounter(void);
void POKEY_SetRandomCounter(ULONG value);
UBYTE POKEY_GetByte(UWORD addr);
void POKEY_PutByte(UWORD addr, UBYTE byte);
int POKEY_Initialise(int *argc, char *argv[]);
void POKEY_Frame(void);
void POKEY_Scanline(void);
void POKEY_StateSave(void);
void POKEY_StateRead(void);
#endif
/* CONSTANT DEFINITIONS */
/* definitions for AUDCx (D201, D203, D205, D207) */
#define POKEY_NOTPOLY5 0x80 /* selects POLY5 or direct CLOCK */
#define POKEY_POLY4 0x40 /* selects POLY4 or POLY17 */
#define POKEY_PURETONE 0x20 /* selects POLY4/17 or PURE tone */
#define POKEY_VOL_ONLY 0x10 /* selects VOLUME OUTPUT ONLY */
#define POKEY_VOLUME_MASK 0x0f /* volume mask */
/* definitions for AUDCTL (D208) */
#define POKEY_POLY9 0x80 /* selects POLY9 or POLY17 */
#define POKEY_CH1_179 0x40 /* selects 1.78979 MHz for Ch 1 */
#define POKEY_CH3_179 0x20 /* selects 1.78979 MHz for Ch 3 */
#define POKEY_CH1_CH2 0x10 /* clocks channel 1 w/channel 2 */
#define POKEY_CH3_CH4 0x08 /* clocks channel 3 w/channel 4 */
#define POKEY_CH1_FILTER 0x04 /* selects channel 1 high pass filter */
#define POKEY_CH2_FILTER 0x02 /* selects channel 2 high pass filter */
#define POKEY_CLOCK_15 0x01 /* selects 15.6999kHz or 63.9210kHz */
/* for accuracy, the 64kHz and 15kHz clocks are exact divisions of
the 1.79MHz clock */
#define POKEY_DIV_64 28 /* divisor for 1.79MHz clock to 64 kHz */
#define POKEY_DIV_15 114 /* divisor for 1.79MHz clock to 15 kHz */
/* the size (in entries) of the 4 polynomial tables */
#define POKEY_POLY4_SIZE 0x000f
#define POKEY_POLY5_SIZE 0x001f
#define POKEY_POLY9_SIZE 0x01ff
#define POKEY_POLY17_SIZE 0x0001ffff
#define POKEY_MAXPOKEYS 2 /* max number of emulated chips */
/* channel/chip definitions */
#define POKEY_CHAN1 0
#define POKEY_CHAN2 1
#define POKEY_CHAN3 2
#define POKEY_CHAN4 3
#define POKEY_CHIP1 0
#define POKEY_CHIP2 4
#define POKEY_CHIP3 8
#define POKEY_CHIP4 12
#define POKEY_SAMPLE 127
/* structures to hold the 9 pokey control bytes */
extern UBYTE POKEY_AUDF[4 * POKEY_MAXPOKEYS]; /* AUDFx (D200, D202, D204, D206) */
extern UBYTE POKEY_AUDC[4 * POKEY_MAXPOKEYS]; /* AUDCx (D201, D203, D205, D207) */
extern UBYTE POKEY_AUDCTL[POKEY_MAXPOKEYS]; /* AUDCTL (D208) */
extern int POKEY_DivNIRQ[4], POKEY_DivNMax[4];
extern int POKEY_Base_mult[POKEY_MAXPOKEYS]; /* selects either 64Khz or 15Khz clock mult */
extern UBYTE POKEY_poly9_lookup[POKEY_POLY9_SIZE];
extern UBYTE POKEY_poly17_lookup[16385];
#endif /* POKEY_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,130 +0,0 @@
/*****************************************************************************/
/* */
/* Module: POKEY Chip Simulator Includes, V2.3 */
/* Purpose: To emulate the sound generation hardware of the Atari POKEY chip. */
/* Author: Ron Fries */
/* */
/* Revision History: */
/* */
/* 09/22/96 - Ron Fries - Initial Release */
/* 04/06/97 - Brad Oliver - Some cross-platform modifications. Added */
/* big/little endian #defines, removed <dos.h>, */
/* conditional defines for TRUE/FALSE */
/* 01/19/98 - Ron Fries - Changed signed/unsigned sample support to a */
/* compile-time option. Defaults to unsigned - */
/* define SIGNED_SAMPLES to create signed. */
/* */
/*****************************************************************************/
/* */
/* License Information and Copyright Notice */
/* ======================================== */
/* */
/* PokeySound is Copyright(c) 1996-1998 by Ron Fries */
/* */
/* This library is free software; you can redistribute it and/or modify it */
/* under the terms of version 2 of the GNU Library General Public License */
/* as published by the Free Software Foundation. */
/* */
/* This library is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */
/* General Public License for more details. */
/* To obtain a copy of the GNU Library General Public License, write to the */
/* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* */
/* Any permitted reproduction of these routines, in whole or in part, must */
/* bear this legend. */
/* */
/*****************************************************************************/
#ifndef POKEYSND_H_
#define POKEYSND_H_
#include "config.h"
#include "pokey.h"
/* CONSTANT DEFINITIONS */
/* As an alternative to using the exact frequencies, selecting a playback
frequency that is an exact division of the main clock provides a higher
quality output due to less aliasing. For best results, a value of
1787520 MHz is used for the main clock. With this value, both the
64 kHz and 15 kHz clocks are evenly divisible. Selecting a playback
frequency that is also a division of the clock provides the best
results. The best options are FREQ_64 divided by either 2, 3, or 4.
The best selection is based on a trade off between performance and
sound quality.
Of course, using a main clock frequency that is not exact will affect
the pitch of the output. With these numbers, the pitch will be low
by 0.127%. (More than likely, an actual unit will vary by this much!) */
#define POKEYSND_FREQ_17_EXACT 1789790 /* exact 1.79 MHz clock freq */
#define POKEYSND_FREQ_17_APPROX 1787520 /* approximate 1.79 MHz clock freq */
#ifdef __cplusplus
extern "C" {
#endif
/* #define SIGNED_SAMPLES */ /* define for signed output */
#ifdef POKEYSND_SIGNED_SAMPLES /* if signed output selected */
#define POKEYSND_SAMP_MAX 127 /* then set signed 8-bit clipping ranges */
#define POKEYSND_SAMP_MIN -128
#define POKEYSND_SAMP_MID 0
#else
#define POKEYSND_SAMP_MAX 255 /* else set unsigned 8-bit clip ranges */
#define POKEYSND_SAMP_MIN 0
#define POKEYSND_SAMP_MID 128
#endif
/* init flags */
#define POKEYSND_BIT16 1
extern SLONG POKEYSND_playback_freq;
extern UBYTE POKEYSND_num_pokeys;
extern int POKEYSND_snd_flags;
extern int POKEYSND_enable_new_pokey;
extern int POKEYSND_stereo_enabled;
extern int POKEYSND_serio_sound_enabled;
extern int POKEYSND_console_sound_enabled;
extern int POKEYSND_bienias_fix;
extern void (*POKEYSND_Process_ptr)(void *sndbuffer, int sndn);
extern void (*POKEYSND_Update)(UWORD addr, UBYTE val, UBYTE /*chip*/, UBYTE gain);
extern void (*POKEYSND_UpdateSerio)(int out, UBYTE data);
extern void (*POKEYSND_UpdateConsol)(int set);
extern void (*POKEYSND_UpdateVolOnly)(void);
int POKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
int flags
#ifdef __PLUS
, int clear_regs
#endif
);
void POKEYSND_Process(void *sndbuffer, int sndn);
int POKEYSND_DoInit(void);
void POKEYSND_SetMzQuality(int quality);
/* Volume only emulations declarations */
#ifdef VOL_ONLY_SOUND
#define POKEYSND_SAMPBUF_MAX 2000
extern int POKEYSND_sampbuf_val[POKEYSND_SAMPBUF_MAX]; /* volume values */
extern int POKEYSND_sampbuf_cnt[POKEYSND_SAMPBUF_MAX]; /* relative start time */
extern int POKEYSND_sampbuf_ptr; /* pointer to sampbuf */
extern int POKEYSND_sampbuf_rptr; /* pointer to read from sampbuf */
extern int POKEYSND_sampbuf_last; /* last absolute time */
extern int POKEYSND_sampbuf_AUDV[4 * POKEY_MAXPOKEYS]; /* prev. channel volume */
extern int POKEYSND_sampbuf_lastval; /* last volume */
extern int POKEYSND_sampout; /* last out volume */
extern int POKEYSND_samp_freq;
extern int POKEYSND_samp_consol_val; /* actual value of console sound */
#endif /* VOL_ONLY_SOUND */
#ifdef __cplusplus
}
#endif
#endif /* POKEYSND_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,41 +0,0 @@
/*
* rdevice.h - Atari850 emulation header file
*
* Copyright (c) ???? Tom Hunt, Chris Martin
* Copyright (c) 2003,2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RDEVICE_H_
#define RDEVICE_H_
extern void RDevice_OPEN(void);
extern void RDevice_CLOS(void);
extern void RDevice_READ(void);
extern void RDevice_WRIT(void);
extern void RDevice_STAT(void);
extern void RDevice_SPEC(void);
extern void RDevice_INIT(void);
extern int RDevice_serial_enabled;
extern char RDevice_serial_device[];
extern void RDevice_Exit(void);
#endif /* RDEVICE_H_ */

View File

@@ -1,643 +0,0 @@
/*
* remez.c - Parks-McClellan algorithm for FIR filter design (C version)
*
* Copyright (C) 1995,1998 Jake Janovetz
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "remez.h"
#ifdef ASAP /* external project, see http://asap.sf.net */
#include "asap_internal.h"
#else
#include "log.h"
#include "util.h"
#endif
#define NEGATIVE 0
#define POSITIVE 1
#define Pi 3.1415926535897932
#define Pi2 6.2831853071795865
#define GRIDDENSITY 16
#define MAXITERATIONS 40
/*******************
* CreateDenseGrid
*=================
* Creates the dense grid of frequencies from the specified bands.
* Also creates the Desired Frequency Response function (D[]) and
* the Weight function (W[]) on that dense grid
*
*
* INPUT:
* ------
* int r - 1/2 the number of filter coefficients
* int numtaps - Number of taps in the resulting filter
* int numband - Number of bands in user specification
* double bands[] - User-specified band edges [2*numband]
* double des[] - Desired response per band [numband]
* double weight[] - Weight per band [numband]
* int symmetry - Symmetry of filter - used for grid check
*
* OUTPUT:
* -------
* int gridsize - Number of elements in the dense frequency grid
* double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
* double D[] - Desired response on the dense grid [gridsize]
* double W[] - Weight function on the dense grid [gridsize]
*******************/
static void CreateDenseGrid(int r, int numtaps, int numband, double bands[],
const double des[], const double weight[],
int *gridsize, double Grid[],
double D[], double W[], int symmetry)
{
int i, j, k, band;
double delf, lowf, highf;
delf = 0.5 / (GRIDDENSITY * r);
/* For differentiator, hilbert,
* symmetry is odd and Grid[0] = max(delf, band[0]) */
if (symmetry == NEGATIVE && delf > bands[0])
bands[0] = delf;
j = 0;
for (band = 0; band < numband; band++) {
Grid[j] = bands[2 * band];
lowf = bands[2 * band];
highf = bands[2 * band + 1];
k = (int) ((highf - lowf) / delf + 0.5); /* .5 for rounding */
for (i = 0; i < k; i++) {
D[j] = des[band];
W[j] = weight[band];
Grid[j] = lowf;
lowf += delf;
j++;
}
Grid[j - 1] = highf;
}
/* Similar to above, if odd symmetry, last grid point can't be .5
* - but, if there are even taps, leave the last grid point at .5 */
if ((symmetry == NEGATIVE) &&
(Grid[*gridsize - 1] > (0.5 - delf)) &&
(numtaps % 2))
{
Grid[*gridsize - 1] = 0.5 - delf;
}
}
/********************
* InitialGuess
*==============
* Places Extremal Frequencies evenly throughout the dense grid.
*
*
* INPUT:
* ------
* int r - 1/2 the number of filter coefficients
* int gridsize - Number of elements in the dense frequency grid
*
* OUTPUT:
* -------
* int Ext[] - Extremal indexes to dense frequency grid [r+1]
********************/
static void InitialGuess(int r, int Ext[], int gridsize)
{
int i;
for (i = 0; i <= r; i++)
Ext[i] = i * (gridsize - 1) / r;
}
/***********************
* CalcParms
*===========
*
*
* INPUT:
* ------
* int r - 1/2 the number of filter coefficients
* int Ext[] - Extremal indexes to dense frequency grid [r+1]
* double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize]
* double D[] - Desired response on the dense grid [gridsize]
* double W[] - Weight function on the dense grid [gridsize]
*
* OUTPUT:
* -------
* double ad[] - 'b' in Oppenheim & Schafer [r+1]
* double x[] - [r+1]
* double y[] - 'C' in Oppenheim & Schafer [r+1]
***********************/
static void CalcParms(int r, const int Ext[], const double Grid[],
const double D[], const double W[],
double ad[], double x[], double y[])
{
int i, j, k, ld;
double sign, xi, delta, denom, numer;
/* Find x[] */
for (i = 0; i <= r; i++)
x[i] = cos(Pi2 * Grid[Ext[i]]);
/* Calculate ad[] - Oppenheim & Schafer eq 7.132 */
ld = (r - 1) / 15 + 1; /* Skips around to avoid round errors */
for (i = 0; i <= r; i++) {
denom = 1.0;
xi = x[i];
for (j = 0; j < ld; j++) {
for (k = j; k <= r; k += ld)
if (k != i)
denom *= 2.0 * (xi - x[k]);
}
if (fabs(denom) < 0.00001)
denom = 0.00001;
ad[i] = 1.0 / denom;
}
/* Calculate delta - Oppenheim & Schafer eq 7.131 */
numer = denom = 0;
sign = 1;
for (i = 0; i <= r; i++) {
numer += ad[i] * D[Ext[i]];
denom += sign * ad[i] / W[Ext[i]];
sign = -sign;
}
delta = numer / denom;
sign = 1;
/* Calculate y[] - Oppenheim & Schafer eq 7.133b */
for (i = 0; i <= r; i++) {
y[i] = D[Ext[i]] - sign * delta / W[Ext[i]];
sign = -sign;
}
}
/*********************
* ComputeA
*==========
* Using values calculated in CalcParms, ComputeA calculates the
* actual filter response at a given frequency (freq). Uses
* eq 7.133a from Oppenheim & Schafer.
*
*
* INPUT:
* ------
* double freq - Frequency (0 to 0.5) at which to calculate A
* int r - 1/2 the number of filter coefficients
* double ad[] - 'b' in Oppenheim & Schafer [r+1]
* double x[] - [r+1]
* double y[] - 'C' in Oppenheim & Schafer [r+1]
*
* OUTPUT:
* -------
* Returns double value of A[freq]
*********************/
static double ComputeA(double freq, int r, const double ad[],
const double x[], const double y[])
{
int i;
double xc, c, denom, numer;
denom = numer = 0;
xc = cos(Pi2 * freq);
for (i = 0; i <= r; i++) {
c = xc - x[i];
if (fabs(c) < 1.0e-7) {
numer = y[i];
denom = 1;
break;
}
c = ad[i] / c;
denom += c;
numer += c * y[i];
}
return numer / denom;
}
/************************
* CalcError
*===========
* Calculates the Error function from the desired frequency response
* on the dense grid (D[]), the weight function on the dense grid (W[]),
* and the present response calculation (A[])
*
*
* INPUT:
* ------
* int r - 1/2 the number of filter coefficients
* double ad[] - [r+1]
* double x[] - [r+1]
* double y[] - [r+1]
* int gridsize - Number of elements in the dense frequency grid
* double Grid[] - Frequencies on the dense grid [gridsize]
* double D[] - Desired response on the dense grid [gridsize]
* double W[] - Weight function on the desnse grid [gridsize]
*
* OUTPUT:
* -------
* double E[] - Error function on dense grid [gridsize]
************************/
static void CalcError(int r, const double ad[],
const double x[], const double y[],
int gridsize, const double Grid[],
const double D[], const double W[], double E[])
{
int i;
double A;
for (i = 0; i < gridsize; i++) {
A = ComputeA(Grid[i], r, ad, x, y);
E[i] = W[i] * (D[i] - A);
}
}
/************************
* Search
*========
* Searches for the maxima/minima of the error curve. If more than
* r+1 extrema are found, it uses the following heuristic (thanks
* Chris Hanson):
* 1) Adjacent non-alternating extrema deleted first.
* 2) If there are more than one excess extrema, delete the
* one with the smallest error. This will create a non-alternation
* condition that is fixed by 1).
* 3) If there is exactly one excess extremum, delete the smaller
* of the first/last extremum
*
*
* INPUT:
* ------
* int r - 1/2 the number of filter coefficients
* int Ext[] - Indexes to Grid[] of extremal frequencies [r+1]
* int gridsize - Number of elements in the dense frequency grid
* double E[] - Array of error values. [gridsize]
* OUTPUT:
* -------
* int Ext[] - New indexes to extremal frequencies [r+1]
************************/
static void Search(int r, int Ext[], int gridsize, const double E[])
{
int i, j, k, l, extra; /* Counters */
int up, alt;
int *foundExt; /* Array of found extremals */
/* Allocate enough space for found extremals. */
foundExt = (int *) Util_malloc((2 * r) * sizeof(int));
k = 0;
/* Check for extremum at 0. */
if (((E[0] > 0.0) && (E[0] > E[1])) ||
((E[0] < 0.0) && (E[0] < E[1])))
foundExt[k++] = 0;
/* Check for extrema inside dense grid */
for (i = 1; i < gridsize - 1; i++) {
if (((E[i] >= E[i - 1]) && (E[i] > E[i + 1]) && (E[i] > 0.0)) ||
((E[i] <= E[i - 1]) && (E[i] < E[i + 1]) && (E[i] < 0.0)))
foundExt[k++] = i;
}
/* Check for extremum at 0.5 */
j = gridsize - 1;
if (((E[j] > 0.0) && (E[j] > E[j - 1])) ||
((E[j] < 0.0) && (E[j] < E[j - 1])))
foundExt[k++] = j;
/* Remove extra extremals */
extra = k - (r + 1);
while (extra > 0) {
if (E[foundExt[0]] > 0.0)
up = 1; /* first one is a maxima */
else
up = 0; /* first one is a minima */
l = 0;
alt = 1;
for (j = 1; j < k; j++) {
if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]]))
l = j; /* new smallest error. */
if ((up) && (E[foundExt[j]] < 0.0))
up = 0; /* switch to a minima */
else if ((!up) && (E[foundExt[j]] > 0.0))
up = 1; /* switch to a maxima */
else {
alt = 0;
break; /* Ooops, found two non-alternating */
} /* extrema. Delete smallest of them */
} /* if the loop finishes, all extrema are alternating */
/* If there's only one extremal and all are alternating,
* delete the smallest of the first/last extremals. */
if ((alt) && (extra == 1)) {
if (fabs(E[foundExt[k - 1]]) < fabs(E[foundExt[0]]))
l = foundExt[k - 1]; /* Delete last extremal */
else
l = foundExt[0]; /* Delete first extremal */
}
/* Loop that does the deletion */
for (j = l; j < k; j++) {
foundExt[j] = foundExt[j+1];
}
k--;
extra--;
}
/* Copy found extremals to Ext[] */
for (i = 0; i <= r; i++) {
Ext[i] = foundExt[i];
}
free(foundExt);
}
/*********************
* FreqSample
*============
* Simple frequency sampling algorithm to determine the impulse
* response h[] from A's found in ComputeA
*
*
* INPUT:
* ------
* int N - Number of filter coefficients
* double A[] - Sample points of desired response [N/2]
* int symm - Symmetry of desired filter
*
* OUTPUT:
* -------
* double h[] - Impulse Response of final filter [N]
*********************/
static void FreqSample(int N, const double A[], double h[], int symm)
{
int n, k;
double x, val, M;
M = (N - 1.0) / 2.0;
if (symm == POSITIVE) {
if (N % 2) {
for (n = 0; n < N; n++) {
val = A[0];
x = Pi2 * (n - M) / N;
for (k = 1; k <= M; k++)
val += 2.0 * A[k] * cos(x * k);
h[n] = val / N;
}
}
else {
for (n = 0; n < N; n++) {
val = A[0];
x = Pi2 * (n - M)/N;
for (k = 1; k <= (N / 2 - 1); k++)
val += 2.0 * A[k] * cos(x * k);
h[n] = val / N;
}
}
}
else {
if (N % 2) {
for (n = 0; n < N; n++) {
val = 0;
x = Pi2 * (n - M) / N;
for (k = 1; k <= M; k++)
val += 2.0 * A[k] * sin(x * k);
h[n] = val / N;
}
}
else {
for (n = 0; n < N; n++) {
val = A[N / 2] * sin(Pi * (n - M));
x = Pi2 * (n - M) / N;
for (k = 1; k <= (N / 2 - 1); k++)
val += 2.0 * A[k] * sin(x * k);
h[n] = val / N;
}
}
}
}
/*******************
* isDone
*========
* Checks to see if the error function is small enough to consider
* the result to have converged.
*
* INPUT:
* ------
* int r - 1/2 the number of filter coeffiecients
* int Ext[] - Indexes to extremal frequencies [r+1]
* double E[] - Error function on the dense grid [gridsize]
*
* OUTPUT:
* -------
* Returns 1 if the result converged
* Returns 0 if the result has not converged
********************/
static int isDone(int r, const int Ext[], const double E[])
{
int i;
double min, max, current;
min = max = fabs(E[Ext[0]]);
for (i = 1; i <= r; i++) {
current = fabs(E[Ext[i]]);
if (current < min)
min = current;
if (current > max)
max = current;
}
if (((max - min) / max) < 0.0001)
return 1;
return 0;
}
/********************
* REMEZ_CreateFilter
*=======
* Calculates the optimal (in the Chebyshev/minimax sense)
* FIR filter impulse response given a set of band edges,
* the desired reponse on those bands, and the weight given to
* the error in those bands.
*
* INPUT:
* ------
* int numtaps - Number of filter coefficients
* int numband - Number of bands in filter specification
* double bands[] - User-specified band edges [2 * numband]
* double des[] - User-specified band responses [numband]
* double weight[] - User-specified error weights [numband]
* int type - Type of filter
*
* OUTPUT:
* -------
* double h[] - Impulse response of final filter [numtaps]
********************/
void REMEZ_CreateFilter(double h[], int numtaps, int numband, double bands[],
const double des[], const double weight[], int type)
{
double *Grid, *W, *D, *E;
int i, iter, gridsize, r, *Ext;
double *taps, c;
double *x, *y, *ad;
int symmetry;
if (type == REMEZ_BANDPASS)
symmetry = POSITIVE;
else
symmetry = NEGATIVE;
r = numtaps / 2; /* number of extrema */
if ((numtaps % 2) && (symmetry == POSITIVE))
r++;
/* Predict dense grid size in advance for memory allocation
* .5 is so we round up, not truncate */
gridsize = 0;
for (i = 0; i < numband; i++) {
gridsize += (int) (2 * r * GRIDDENSITY *
(bands[2 * i + 1] - bands[2 * i]) + .5);
}
if (symmetry == NEGATIVE) {
gridsize--;
}
/* Dynamically allocate memory for arrays with proper sizes */
Grid = (double *) Util_malloc(gridsize * sizeof(double));
D = (double *) Util_malloc(gridsize * sizeof(double));
W = (double *) Util_malloc(gridsize * sizeof(double));
E = (double *) Util_malloc(gridsize * sizeof(double));
Ext = (int *) Util_malloc((r + 1) * sizeof(int));
taps = (double *) Util_malloc((r + 1) * sizeof(double));
x = (double *) Util_malloc((r + 1) * sizeof(double));
y = (double *) Util_malloc((r + 1) * sizeof(double));
ad = (double *) Util_malloc((r + 1) * sizeof(double));
/* Create dense frequency grid */
CreateDenseGrid(r, numtaps, numband, bands, des, weight,
&gridsize, Grid, D, W, symmetry);
InitialGuess(r, Ext, gridsize);
/* For Differentiator: (fix grid) */
if (type == REMEZ_DIFFERENTIATOR) {
for (i = 0; i < gridsize; i++) {
/* D[i] = D[i] * Grid[i]; */
if (D[i] > 0.0001)
W[i] = W[i] / Grid[i];
}
}
/* For odd or Negative symmetry filters, alter the
* D[] and W[] according to Parks McClellan */
if (symmetry == POSITIVE) {
if (numtaps % 2 == 0) {
for (i = 0; i < gridsize; i++) {
c = cos(Pi * Grid[i]);
D[i] /= c;
W[i] *= c;
}
}
}
else {
if (numtaps % 2) {
for (i = 0; i < gridsize; i++) {
c = sin(Pi2 * Grid[i]);
D[i] /= c;
W[i] *= c;
}
}
else {
for (i = 0; i < gridsize; i++) {
c = sin(Pi * Grid[i]);
D[i] /= c;
W[i] *= c;
}
}
}
/* Perform the Remez Exchange algorithm */
for (iter = 0; iter < MAXITERATIONS; iter++) {
CalcParms(r, Ext, Grid, D, W, ad, x, y);
CalcError(r, ad, x, y, gridsize, Grid, D, W, E);
Search(r, Ext, gridsize, E);
if (isDone(r, Ext, E))
break;
}
#ifndef ASAP
if (iter == MAXITERATIONS) {
Log_print("remez(): reached maximum iteration count. Results may be bad.");
}
#endif
CalcParms(r, Ext, Grid, D, W, ad, x, y);
/* Find the 'taps' of the filter for use with Frequency
* Sampling. If odd or Negative symmetry, fix the taps
* according to Parks McClellan */
for (i = 0; i <= numtaps / 2; i++) {
if (symmetry == POSITIVE) {
if (numtaps % 2)
c = 1;
else
c = cos(Pi * (double) i / numtaps);
}
else {
if (numtaps % 2)
c = sin(Pi2 * (double) i / numtaps);
else
c = sin(Pi * (double) i / numtaps);
}
taps[i] = ComputeA((double) i / numtaps, r, ad, x, y) * c;
}
/* Frequency sampling design with calculated taps */
FreqSample(numtaps, taps, h, symmetry);
/* Delete allocated memory */
free(Grid);
free(W);
free(D);
free(E);
free(Ext);
free(taps);
free(x);
free(y);
free(ad);
}

View File

@@ -1,34 +0,0 @@
/**************************************************************************
* Parks-McClellan algorithm for FIR filter design (C version)
*-------------------------------------------------
* Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*************************************************************************/
#ifndef REMEZ_H_
#define REMEZ_H_
#define REMEZ_BANDPASS 1
#define REMEZ_DIFFERENTIATOR 2
#define REMEZ_HILBERT 3
/* Function prototype for REMEZ_CreateFilter() - the only function that should need be
* called from external code */
void REMEZ_CreateFilter(double h[], int numtaps,
int numband, double bands[], const double des[], const double weight[],
int type);
#endif /* REMEZ_H_ */

View File

@@ -1,173 +0,0 @@
/*
* rtime.c - Emulate ICD R-Time 8 cartridge
*
* Copyright (C) 2000 Jason Duerstock
* Copyright (C) 2000-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdlib.h> /* for NULL */
#include <string.h> /* for strcmp() */
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include "atari.h"
#include "log.h"
#include "rtime.h"
int RTIME_enabled = 1;
static int rtime_state = 0;
/* 0 = waiting for register # */
/* 1 = got register #, waiting for hi nybble */
/* 2 = got hi nybble, waiting for lo nybble */
static int rtime_tmp = 0;
static int rtime_tmp2 = 0;
static UBYTE regset[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int RTIME_Initialise(int *argc, char *argv[])
{
int i;
int j;
for (i = j = 1; i < *argc; i++) {
if (strcmp(argv[i], "-rtime") == 0)
RTIME_enabled = TRUE;
else if (strcmp(argv[i], "-nortime") == 0)
RTIME_enabled = FALSE;
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-rtime Enable R-Time 8 emulation");
Log_print("\t-nortime Disable R-Time 8 emulation");
}
argv[j++] = argv[i];
}
}
*argc = j;
return TRUE;
}
#if defined(WIN32) || (defined(HAVE_TIME) && defined(HAVE_LOCALTIME))
static int hex2bcd(int h)
{
return ((h / 10) << 4) | (h % 10);
}
static int gettime(int p)
{
#ifdef WIN32
SYSTEMTIME st;
GetLocalTime(&st);
switch (p) {
case 0:
return hex2bcd(st.wSecond);
case 1:
return hex2bcd(st.wMinute);
case 2:
return hex2bcd(st.wHour);
case 3:
return hex2bcd(st.wDay);
case 4:
return hex2bcd(st.wMonth);
case 5:
return hex2bcd(st.wYear % 100);
case 6:
return hex2bcd(((st.wDayOfWeek + 2) % 7) + 1);
}
#else /* WIN32 */
time_t tt;
struct tm *lt;
tt = time(NULL);
lt = localtime(&tt);
switch (p) {
case 0:
return hex2bcd(lt->tm_sec);
case 1:
return hex2bcd(lt->tm_min);
case 2:
return hex2bcd(lt->tm_hour);
case 3:
return hex2bcd(lt->tm_mday);
case 4:
return hex2bcd(lt->tm_mon + 1);
case 5:
return hex2bcd(lt->tm_year % 100);
case 6:
return hex2bcd(((lt->tm_wday + 2) % 7) + 1);
}
#endif /* WIN32 */
return 0;
}
#define HAVE_GETTIME
#endif /* defined(WIN32) || (defined(HAVE_TIME) && defined(HAVE_LOCALTIME)) */
UBYTE RTIME_GetByte(void)
{
switch (rtime_state) {
case 0:
/* Log_print("pretending rtime not busy, returning 0"); */
return 0;
case 1:
rtime_state = 2;
return (
#ifdef HAVE_GETTIME
rtime_tmp <= 6 ?
gettime(rtime_tmp) :
#endif
regset[rtime_tmp]) >> 4;
case 2:
rtime_state = 0;
return (
#ifdef HAVE_GETTIME
rtime_tmp <= 6 ?
gettime(rtime_tmp) :
#endif
regset[rtime_tmp]) & 0x0f;
}
return 0;
}
void RTIME_PutByte(UBYTE byte)
{
switch (rtime_state) {
case 0:
rtime_tmp = byte & 0x0f;
rtime_state = 1;
break;
case 1:
rtime_tmp2 = byte << 4;
rtime_state = 2;
break;
case 2:
regset[rtime_tmp] = rtime_tmp2 | (byte & 0x0f);
rtime_state = 0;
break;
}
}

View File

@@ -1,27 +0,0 @@
#ifndef RTIME_H_
#define RTIME_H_
/* Emulate ICD R-Time 8 cartridge
Copyright 2000 Jason Duerstock <jason@cluephone.com>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include "atari.h"
extern int RTIME_enabled;
int RTIME_Initialise(int *argc, char *argv[]);
UBYTE RTIME_GetByte(void);
void RTIME_PutByte(UBYTE byte);
#endif /* RTIME_H_ */

View File

@@ -1,587 +0,0 @@
/*
* screen.c - Atari screen handling
*
* Copyright (c) 2001 Robert Golias and Piotr Fusik
* Copyright (C) 2001-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_LIBPNG
#include <png.h>
#endif
#include "antic.h"
#include "atari.h"
#include "colours.h"
#include "log.h"
#include "screen.h"
#include "sio.h"
#include "util.h"
#define ATARI_VISIBLE_WIDTH 336
#define ATARI_LEFT_MARGIN 24
ULONG *Screen_atari = NULL;
#ifdef DIRTYRECT
UBYTE *Screen_dirty = NULL;
#endif
#ifdef BITPL_SCR
ULONG *Screen_atari_b = NULL;
ULONG *Screen_atari1 = NULL;
ULONG *Screen_atari2 = NULL;
#endif
/* The area that can been seen is Screen_visible_x1 <= x < Screen_visible_x2,
Screen_visible_y1 <= y < Screen_visible_y2.
Full Atari screen is 336x240. Screen_WIDTH is 384 only because
the code in antic.c sometimes draws more than 336 bytes in a line.
Currently Screen_visible variables are used only to place
disk led and snailmeter in the corners of the screen.
*/
int Screen_visible_x1 = 24; /* 0 .. Screen_WIDTH */
int Screen_visible_y1 = 0; /* 0 .. Screen_HEIGHT */
int Screen_visible_x2 = 360; /* 0 .. Screen_WIDTH */
int Screen_visible_y2 = Screen_HEIGHT; /* 0 .. Screen_HEIGHT */
int Screen_show_atari_speed = FALSE;
int Screen_show_disk_led = TRUE;
int Screen_show_sector_counter = FALSE;
#ifdef HAVE_LIBPNG
#define DEFAULT_SCREENSHOT_FILENAME_FORMAT "atari%03d.png"
#else
#define DEFAULT_SCREENSHOT_FILENAME_FORMAT "atari%03d.pcx"
#endif
static char screenshot_filename_format[FILENAME_MAX] = DEFAULT_SCREENSHOT_FILENAME_FORMAT;
static int screenshot_no_max = 1000;
/* converts "foo%bar##.pcx" to "foo%%bar%02d.pcx" */
static void Screen_SetScreenshotFilenamePattern(const char *p)
{
char *f = screenshot_filename_format;
char no_width = '0';
screenshot_no_max = 1;
/* 9 because sprintf'ed "no" can be 9 digits */
while (f < screenshot_filename_format + FILENAME_MAX - 9) {
/* replace a sequence of hashes with e.g. "%05d" */
if (*p == '#') {
if (no_width > '0') /* already seen a sequence of hashes */
break; /* invalid */
/* count hashes */
do {
screenshot_no_max *= 10;
p++;
no_width++;
/* now no_width is the number of hashes seen so far
and p points after the counted hashes */
} while (no_width < '9' && *p == '#'); /* no more than 9 hashes */
*f++ = '%';
*f++ = '0';
*f++ = no_width;
*f++ = 'd';
continue;
}
if (*p == '%')
*f++ = '%'; /* double the percents */
*f++ = *p;
if (*p == '\0')
return; /* ok */
p++;
}
Log_print("Invalid filename pattern for screenshots, using default.");
strcpy(screenshot_filename_format, DEFAULT_SCREENSHOT_FILENAME_FORMAT);
screenshot_no_max = 1000;
}
int Screen_Initialise(int *argc, char *argv[])
{
int i;
int j;
int help_only = FALSE;
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = FALSE; /* error, argument missing! */
if (strcmp(argv[i], "-screenshots") == 0) {
if (i_a)
Screen_SetScreenshotFilenamePattern(argv[++i]);
else a_m = TRUE;
}
if (strcmp(argv[i], "-showspeed") == 0) {
Screen_show_atari_speed = TRUE;
}
else {
if (strcmp(argv[i], "-help") == 0) {
help_only = TRUE;
Log_print("\t-screenshots <p> Set filename pattern for screenshots");
Log_print("\t-showspeed Show percentage of actual speed");
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return FALSE;
}
}
*argc = j;
/* don't bother mallocing Screen_atari with just "-help" */
if (help_only)
return TRUE;
if (Screen_atari == NULL) { /* platform-specific code can initialize it in theory */
Screen_atari = (ULONG *) Util_malloc(Screen_HEIGHT * Screen_WIDTH);
#ifdef DIRTYRECT
Screen_dirty = (UBYTE *) Util_malloc(Screen_HEIGHT * Screen_WIDTH / 8);
Screen_EntireDirty();
#endif
#ifdef BITPL_SCR
Screen_atari_b = (ULONG *) Util_malloc(Screen_HEIGHT * Screen_WIDTH);
Screen_atari1 = Screen_atari;
Screen_atari2 = Screen_atari_b;
#endif
}
return TRUE;
}
#define SMALLFONT_WIDTH 5
#define SMALLFONT_HEIGHT 7
#define SMALLFONT_PERCENT 10
#define SMALLFONT_____ 0x00
#define SMALLFONT___X_ 0x02
#define SMALLFONT__X__ 0x04
#define SMALLFONT__XX_ 0x06
#define SMALLFONT_X___ 0x08
#define SMALLFONT_X_X_ 0x0A
#define SMALLFONT_XX__ 0x0C
#define SMALLFONT_XXX_ 0x0E
static void SmallFont_DrawChar(UBYTE *screen, int ch, UBYTE color1, UBYTE color2)
{
static const UBYTE font[12][SMALLFONT_HEIGHT] = {
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_X_X_,
SMALLFONT_X_X_,
SMALLFONT_X_X_,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_XX__,
SMALLFONT__X__,
SMALLFONT__X__,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT_XX__,
SMALLFONT___X_,
SMALLFONT__X__,
SMALLFONT_X___,
SMALLFONT_XXX_,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT_XX__,
SMALLFONT___X_,
SMALLFONT__X__,
SMALLFONT___X_,
SMALLFONT_XX__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT___X_,
SMALLFONT__XX_,
SMALLFONT_X_X_,
SMALLFONT_XXX_,
SMALLFONT___X_,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT_XXX_,
SMALLFONT_X___,
SMALLFONT_XXX_,
SMALLFONT___X_,
SMALLFONT_XX__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_X___,
SMALLFONT_XX__,
SMALLFONT_X_X_,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT_XXX_,
SMALLFONT___X_,
SMALLFONT__X__,
SMALLFONT__X__,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_X_X_,
SMALLFONT__X__,
SMALLFONT_X_X_,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_X_X_,
SMALLFONT__XX_,
SMALLFONT___X_,
SMALLFONT__X__,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT_X_X_,
SMALLFONT___X_,
SMALLFONT__X__,
SMALLFONT_X___,
SMALLFONT_X_X_,
SMALLFONT_____
},
{
SMALLFONT_____,
SMALLFONT__X__,
SMALLFONT_X_X_,
SMALLFONT_X___,
SMALLFONT_X_X_,
SMALLFONT__X__,
SMALLFONT_____
}
};
int y;
for (y = 0; y < SMALLFONT_HEIGHT; y++) {
int src;
int mask;
src = font[ch][y];
for (mask = 1 << (SMALLFONT_WIDTH - 1); mask != 0; mask >>= 1) {
ANTIC_VideoPutByte(screen, (UBYTE) ((src & mask) != 0 ? color1 : color2));
screen++;
}
screen += Screen_WIDTH - SMALLFONT_WIDTH;
}
}
static void SmallFont_DrawInt(UBYTE *screen, int n, UBYTE color1, UBYTE color2)
{
do {
SmallFont_DrawChar(screen, n % 10, color1, color2);
screen -= SMALLFONT_WIDTH;
n /= 10;
} while (n > 0);
}
void Screen_DrawAtariSpeed(double cur_time)
{
if (Screen_show_atari_speed) {
static int percent_display = 100;
static int last_updated = 0;
static double last_time = 0;
if ((cur_time - last_time) >= 0.5) {
percent_display = (int) (100 * (Atari800_nframes - last_updated) / (cur_time - last_time) / (Atari800_tv_mode == Atari800_TV_PAL ? 50 : 60));
last_updated = Atari800_nframes;
last_time = cur_time;
}
/* if (percent_display < 99 || percent_display > 101) */
{
/* space for 5 digits - up to 99999% Atari speed */
UBYTE *screen = (UBYTE *) Screen_atari + Screen_visible_x1 + 5 * SMALLFONT_WIDTH
+ (Screen_visible_y2 - SMALLFONT_HEIGHT) * Screen_WIDTH;
SmallFont_DrawChar(screen, SMALLFONT_PERCENT, 0x0c, 0x00);
SmallFont_DrawInt(screen - SMALLFONT_WIDTH, percent_display, 0x0c, 0x00);
}
}
}
void Screen_DrawDiskLED(void)
{
if (SIO_last_op_time > 0) {
UBYTE *screen;
if (SIO_last_drive != 0x60)
SIO_last_op_time--;
screen = (UBYTE *) Screen_atari + Screen_visible_x2 - SMALLFONT_WIDTH
+ (Screen_visible_y2 - SMALLFONT_HEIGHT) * Screen_WIDTH;
if (SIO_last_drive == 0x60 || SIO_last_drive == 0x61) {
if (Screen_show_disk_led)
SmallFont_DrawChar(screen, 11, 0x00, (UBYTE) (SIO_last_op == SIO_LAST_READ ? 0xac : 0x2b));
}
else {
if (Screen_show_disk_led)
SmallFont_DrawChar(screen, SIO_last_drive, 0x00, (UBYTE) (SIO_last_op == SIO_LAST_READ ? 0xac : 0x2b));
if (Screen_show_sector_counter)
SmallFont_DrawInt(screen - SMALLFONT_WIDTH, SIO_last_sector, 0x00, 0x88);
}
}
}
void Screen_FindScreenshotFilename(char *buffer)
{
static int no = -1;
static int overwrite = FALSE;
for (;;) {
if (++no >= screenshot_no_max) {
no = 0;
overwrite = TRUE;
}
sprintf(buffer, screenshot_filename_format, no);
if (overwrite)
break;
if (!Util_fileexists(buffer))
break; /* file does not exist - we can create it */
}
}
static void fputw(int x, FILE *fp)
{
fputc(x & 0xff, fp);
fputc(x >> 8, fp);
}
static void Screen_SavePCX(FILE *fp, UBYTE *ptr1, UBYTE *ptr2)
{
int i;
int x;
int y;
UBYTE plane = 16; /* 16 = Red, 8 = Green, 0 = Blue */
UBYTE last;
UBYTE count;
fputc(0xa, fp); /* pcx signature */
fputc(0x5, fp); /* version 5 */
fputc(0x1, fp); /* RLE encoding */
fputc(0x8, fp); /* bits per pixel */
fputw(0, fp); /* XMin */
fputw(0, fp); /* YMin */
fputw(ATARI_VISIBLE_WIDTH - 1, fp); /* XMax */
fputw(Screen_HEIGHT - 1, fp); /* YMax */
fputw(0, fp); /* HRes */
fputw(0, fp); /* VRes */
for (i = 0; i < 48; i++)
fputc(0, fp); /* EGA color palette */
fputc(0, fp); /* reserved */
fputc(ptr2 != NULL ? 3 : 1, fp); /* number of bit planes */
fputw(ATARI_VISIBLE_WIDTH, fp); /* number of bytes per scan line per color plane */
fputw(1, fp); /* palette info */
fputw(ATARI_VISIBLE_WIDTH, fp); /* screen resolution */
fputw(Screen_HEIGHT, fp);
for (i = 0; i < 54; i++)
fputc(0, fp); /* unused */
for (y = 0; y < Screen_HEIGHT; ) {
x = 0;
do {
last = ptr2 != NULL ? (((Colours_table[*ptr1] >> plane) & 0xff) + ((Colours_table[*ptr2] >> plane) & 0xff)) >> 1 : *ptr1;
count = 0xc0;
do {
ptr1++;
if (ptr2 != NULL)
ptr2++;
count++;
x++;
} while (last == (ptr2 != NULL ? (((Colours_table[*ptr1] >> plane) & 0xff) + ((Colours_table[*ptr2] >> plane) & 0xff)) >> 1 : *ptr1)
&& count < 0xff && x < ATARI_VISIBLE_WIDTH);
if (count > 0xc1 || last >= 0xc0)
fputc(count, fp);
fputc(last, fp);
} while (x < ATARI_VISIBLE_WIDTH);
if (ptr2 != NULL && plane) {
ptr1 -= ATARI_VISIBLE_WIDTH;
ptr2 -= ATARI_VISIBLE_WIDTH;
plane -= 8;
}
else {
ptr1 += Screen_WIDTH - ATARI_VISIBLE_WIDTH;
if (ptr2 != NULL) {
ptr2 += Screen_WIDTH - ATARI_VISIBLE_WIDTH;
plane = 16;
}
y++;
}
}
if (ptr2 == NULL) {
/* write palette */
fputc(0xc, fp);
for (i = 0; i < 256; i++) {
fputc(Colours_GetR(i), fp);
fputc(Colours_GetG(i), fp);
fputc(Colours_GetB(i), fp);
}
}
}
static int striendswith(const char *s1, const char *s2)
{
int pos;
pos = strlen(s1) - strlen(s2);
if (pos < 0)
return 0;
return Util_stricmp(s1 + pos, s2) == 0;
}
#ifdef HAVE_LIBPNG
static void Screen_SavePNG(FILE *fp, UBYTE *ptr1, UBYTE *ptr2)
{
png_structp png_ptr;
png_infop info_ptr;
png_bytep rows[Screen_HEIGHT];
png_ptr = png_create_write_struct(
PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL
);
if (png_ptr == NULL)
return;
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
return;
png_init_io(png_ptr, fp);
png_set_IHDR(
png_ptr, info_ptr, ATARI_VISIBLE_WIDTH, Screen_HEIGHT,
8, ptr2 == NULL ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT
);
if (ptr2 == NULL) {
int i;
png_color palette[256];
for (i = 0; i < 256; i++) {
palette[i].red = Colours_GetR(i);
palette[i].green = Colours_GetG(i);
palette[i].blue = Colours_GetB(i);
}
png_set_PLTE(png_ptr, info_ptr, palette, 256);
for (i = 0; i < Screen_HEIGHT; i++) {
rows[i] = ptr1;
ptr1 += Screen_WIDTH;
}
}
else {
png_bytep ptr3;
int x;
int y;
ptr3 = (png_bytep) Util_malloc(3 * ATARI_VISIBLE_WIDTH * Screen_HEIGHT);
for (y = 0; y < Screen_HEIGHT; y++) {
rows[y] = ptr3;
for (x = 0; x < ATARI_VISIBLE_WIDTH; x++) {
*ptr3++ = (png_byte) ((Colours_GetR(*ptr1) + Colours_GetR(*ptr2)) >> 1);
*ptr3++ = (png_byte) ((Colours_GetG(*ptr1) + Colours_GetG(*ptr2)) >> 1);
*ptr3++ = (png_byte) ((Colours_GetB(*ptr1) + Colours_GetB(*ptr2)) >> 1);
ptr1++;
ptr2++;
}
ptr1 += Screen_WIDTH - ATARI_VISIBLE_WIDTH;
ptr2 += Screen_WIDTH - ATARI_VISIBLE_WIDTH;
}
}
png_set_rows(png_ptr, info_ptr, rows);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
if (ptr2 != NULL)
free(rows[0]);
}
#endif /* HAVE_LIBPNG */
int Screen_SaveScreenshot(const char *filename, int interlaced)
{
int is_png;
FILE *fp;
ULONG *main_screen_atari;
UBYTE *ptr1;
UBYTE *ptr2;
if (striendswith(filename, ".pcx"))
is_png = 0;
#ifdef HAVE_LIBPNG
else if (striendswith(filename, ".png"))
is_png = 1;
#endif
else
return FALSE;
fp = fopen(filename, "wb");
if (fp == NULL)
return FALSE;
main_screen_atari = Screen_atari;
ptr1 = (UBYTE *) Screen_atari + ATARI_LEFT_MARGIN;
if (interlaced) {
Screen_atari = (ULONG *) Util_malloc(Screen_WIDTH * Screen_HEIGHT);
ptr2 = (UBYTE *) Screen_atari + ATARI_LEFT_MARGIN;
ANTIC_Frame(TRUE); /* draw on Screen_atari */
}
else {
ptr2 = NULL;
}
#ifdef HAVE_LIBPNG
if (is_png)
Screen_SavePNG(fp, ptr1, ptr2);
else
#endif
Screen_SavePCX(fp, ptr1, ptr2);
fclose(fp);
if (interlaced) {
free(Screen_atari);
Screen_atari = main_screen_atari;
}
return TRUE;
}
void Screen_SaveNextScreenshot(int interlaced)
{
char filename[FILENAME_MAX];
Screen_FindScreenshotFilename(filename);
Screen_SaveScreenshot(filename, interlaced);
}
void Screen_EntireDirty(void)
{
#ifdef DIRTYRECT
memset(Screen_dirty, 1, Screen_WIDTH * Screen_HEIGHT / 8);
#endif /* DIRTYRECT */
}

View File

@@ -1,45 +0,0 @@
#ifndef SCREEN_H_
#define SCREEN_H_
#include "atari.h" /* UBYTE */
#ifdef DIRTYRECT
#ifndef CLIENTUPDATE
extern UBYTE *Screen_dirty;
#endif /* CLIENTUPDATE */
#endif /* DIRTYRECT */
extern ULONG *Screen_atari;
/* Dimensions of Screen_atari.
Screen_atari is Screen_WIDTH * Screen_HEIGHT bytes.
Each byte is an Atari color code - use Colours_Get[RGB] functions
to get actual RGB codes.
You should never display anything outside the middle 336 columns. */
#define Screen_WIDTH 384
#define Screen_HEIGHT 240
#ifdef BITPL_SCR
extern ULONG *Screen_atari_b;
extern ULONG *Screen_atari1;
extern ULONG *Screen_atari2;
#endif
extern int Screen_visible_x1;
extern int Screen_visible_y1;
extern int Screen_visible_x2;
extern int Screen_visible_y2;
extern int Screen_show_atari_speed;
extern int Screen_show_disk_led;
extern int Screen_show_sector_counter;
int Screen_Initialise(int *argc, char *argv[]);
void Screen_DrawAtariSpeed(double);
void Screen_DrawDiskLED(void);
void Screen_FindScreenshotFilename(char *buffer);
int Screen_SaveScreenshot(const char *filename, int interlaced);
void Screen_SaveNextScreenshot(int interlaced);
void Screen_EntireDirty(void);
#endif /* SCREEN_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
#ifndef SIO_H_
#define SIO_H_
#include "config.h"
#include <stdio.h> /* FILENAME_MAX */
#include "atari.h"
#define SIO_MAX_DRIVES 8
typedef enum SIO_tagUnitStatus {
SIO_OFF,
SIO_NO_DISK,
SIO_READ_ONLY,
SIO_READ_WRITE
} SIO_UnitStatus;
extern char SIO_status[256];
extern SIO_UnitStatus SIO_drive_status[SIO_MAX_DRIVES];
extern char SIO_filename[SIO_MAX_DRIVES][FILENAME_MAX];
#define SIO_LAST_READ 0
#define SIO_LAST_WRITE 1
extern int SIO_last_op;
extern int SIO_last_op_time;
extern int SIO_last_drive; /* 1 .. 8 */
extern int SIO_last_sector;
int SIO_Mount(int diskno, const char *filename, int b_open_readonly);
void SIO_Dismount(int diskno);
void SIO_DisableDrive(int diskno);
int SIO_RotateDisks(void);
void SIO_Handler(void);
UBYTE SIO_ChkSum(const UBYTE *buffer, int length);
void SIO_TapeMotor(int onoff);
void SIO_SwitchCommandFrame(int onoff);
void SIO_PutByte(int byte);
int SIO_GetByte(void);
int SIO_Initialise(int *argc, char *argv[]);
void SIO_Exit(void);
/* Some defines about the serial I/O timing. Currently fixed! */
#define SIO_XMTDONE_INTERVAL 15
#define SIO_SERIN_INTERVAL 8
#define SIO_SEROUT_INTERVAL 8
#define SIO_ACK_INTERVAL 36
/* These functions are also used by the 1450XLD Parallel disk device */
extern int SIO_format_sectorcount[SIO_MAX_DRIVES];
extern int SIO_format_sectorsize[SIO_MAX_DRIVES];
int SIO_ReadStatusBlock(int unit, UBYTE *buffer);
int SIO_FormatDisk(int unit, UBYTE *buffer, int sectsize, int sectcount);
void SIO_SizeOfSector(UBYTE unit, int sector, int *sz, ULONG *ofs);
int SIO_ReadSector(int unit, int sector, UBYTE *buffer);
int SIO_DriveStatus(int unit, UBYTE *buffer);
int SIO_WriteStatusBlock(int unit, const UBYTE *buffer);
int SIO_WriteSector(int unit, int sector, const UBYTE *buffer);
void SIO_StateSave(void);
void SIO_StateRead(void);
#endif /* SIO_H_ */

View File

@@ -1,191 +0,0 @@
/*
* sndsave.c - reading and writing sound to files
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include "pokeysnd.h"
#include "sndsave.h"
/* sndoutput is just the file pointer for the current sound file */
static FILE *sndoutput = NULL;
static ULONG byteswritten;
/* write 32-bit word as little endian */
static void write32(long x)
{
fputc(x & 0xff, sndoutput);
fputc((x >> 8) & 0xff, sndoutput);
fputc((x >> 16) & 0xff, sndoutput);
fputc((x >> 24) & 0xff, sndoutput);
}
/* SndSave_IsSoundFileOpen simply returns true if the sound file is currently open and able to receive writes
RETURNS: TRUE is file is open, FALSE if it is not */
int SndSave_IsSoundFileOpen(void)
{
return sndoutput != NULL;
}
/* SndSave_CloseSoundFile should be called when the program is exiting, or when all data required has been
written to the file. SndSave_CloseSoundFile will also be called automatically when a call is made to
SndSave_OpenSoundFile, or an error is made in SndSave_WriteToSoundFile. Note that CloseSoundFile has to back track
to the header written out in SndSave_OpenSoundFile and update it with the length of samples written
RETURNS: TRUE if file closed with no problems, FALSE if failure during close */
int SndSave_CloseSoundFile(void)
{
int bSuccess = TRUE;
char aligned = 0;
if (sndoutput != NULL) {
/* A RIFF file's chunks must be word-aligned. So let's align. */
if (byteswritten & 1) {
if (putc(0, sndoutput) == EOF)
bSuccess = FALSE;
else
aligned = 1;
}
if (bSuccess) {
/* Sound file is finished, so modify header and close it. */
if (fseek(sndoutput, 4, SEEK_SET) != 0) /* Seek past RIFF */
bSuccess = FALSE;
else {
/* RIFF header's size field must equal the size of all chunks
* with alignment, so the alignment byte is added.
*/
write32(byteswritten + 36 + aligned);
if (fseek(sndoutput, 40, SEEK_SET) != 0)
bSuccess = FALSE;
else {
/* But in the "data" chunk size field, the alignment byte
* should be ignored. */
write32(byteswritten);
}
}
}
fclose(sndoutput);
sndoutput = NULL;
}
return bSuccess;
}
/* SndSave_OpenSoundFile will start a new sound file and write out the header. If an existing sound file is
already open it will be closed first, and the new file opened in it's place
RETURNS: TRUE if file opened with no problems, FALSE if failure during open */
int SndSave_OpenSoundFile(const char *szFileName)
{
SndSave_CloseSoundFile();
sndoutput = fopen(szFileName, "wb");
if (sndoutput == NULL)
return FALSE;
/*
The RIFF header:
Offset Length Contents
0 4 bytes 'RIFF'
4 4 bytes <file length - 8>
8 4 bytes 'WAVE'
The fmt chunk:
12 4 bytes 'fmt '
16 4 bytes 0x00000010 // Length of the fmt data (16 bytes)
20 2 bytes 0x0001 // Format tag: 1 = PCM
22 2 bytes <channels> // Channels: 1 = mono, 2 = stereo
24 4 bytes <sample rate> // Samples per second: e.g., 44100
28 4 bytes <bytes/second> // sample rate * block align
32 2 bytes <block align> // channels * bits/sample / 8
34 2 bytes <bits/sample> // 8 or 16
The data chunk:
36 4 bytes 'data'
40 4 bytes <length of the data block>
44 bytes <sample data>
All chunks must be word-aligned.
Good description of WAVE format: http://www.sonicspot.com/guide/wavefiles.html
*/
if (fwrite("RIFF\0\0\0\0WAVEfmt \x10\0\0\0\1\0", 1, 22, sndoutput) != 22) {
fclose(sndoutput);
sndoutput = NULL;
return FALSE;
}
fputc(POKEYSND_num_pokeys, sndoutput);
fputc(0, sndoutput);
write32(POKEYSND_playback_freq);
write32(POKEYSND_playback_freq * (POKEYSND_snd_flags & POKEYSND_BIT16 ? POKEYSND_num_pokeys << 1 : POKEYSND_num_pokeys));
fputc(POKEYSND_snd_flags & POKEYSND_BIT16 ? POKEYSND_num_pokeys << 1 : POKEYSND_num_pokeys, sndoutput);
fputc(0, sndoutput);
fputc(POKEYSND_snd_flags & POKEYSND_BIT16? 16: 8, sndoutput);
if (fwrite("\0data\0\0\0\0", 1, 9, sndoutput) != 9) {
fclose(sndoutput);
sndoutput = NULL;
return FALSE;
}
byteswritten = 0;
return TRUE;
}
/* SndSave_WriteToSoundFile will dump PCM data to the WAV file. The best way to do this for Atari800 is
probably to call it directly after POKEYSND_Process(buffer, size) with the same values (buffer, size)
RETURNS: the number of bytes written to the file (should be equivalent to the input uiSize parm) */
int SndSave_WriteToSoundFile(const unsigned char *ucBuffer, unsigned int uiSize)
{
/* XXX FIXME: doesn't work with big-endian architectures */
if (sndoutput && ucBuffer && uiSize) {
int result;
if (POKEYSND_snd_flags & POKEYSND_BIT16)
uiSize <<= 1;
result = fwrite(ucBuffer, 1, uiSize, sndoutput);
byteswritten += result;
if (result != uiSize) {
SndSave_CloseSoundFile();
}
return result;
}
return 0;
}

View File

@@ -1,12 +0,0 @@
#ifndef SNDSAVE_H_
#define SNDSAVE_H_
#include "atari.h"
int SndSave_IsSoundFileOpen(void);
int SndSave_CloseSoundFile(void);
int SndSave_OpenSoundFile(const char *szFileName);
int SndSave_WriteToSoundFile(const UBYTE *ucBuffer, unsigned int uiSize);
#endif /* SNDSAVE_H_ */

View File

@@ -1,13 +0,0 @@
#ifndef SOUND_H_
#define SOUND_H_
void Sound_Initialise(int *argc, char *argv[]);
void Sound_Exit(void);
void Sound_Update(void);
void Sound_Pause(void);
void Sound_Continue(void);
#ifdef SUPPORTS_SOUND_REINIT
void Sound_Reinit(void);
#endif
#endif /* SOUND_H_ */

View File

@@ -1,662 +0,0 @@
/*
* statesav.c - saving the emulator's state to a file
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* getcwd */
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h> /* getcwd on MSVC*/
#endif
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#ifdef DREAMCAST
#include <bzlib/bzlib.h>
#define MEMCOMPR /* compress in memory before writing */
#include "vmu.h"
#include "icon.h"
#include "version.h"
#endif
#include "atari.h"
#include "statesav.h"
#include "antic.h"
#include "cartridge.h"
#include "cpu.h"
#include "gtia.h"
#include "log.h"
#include "pbi.h"
#include "pia.h"
#include "pokey.h"
#include "sio.h"
#include "util.h"
#ifdef PBI_MIO
#include "pbi_mio.h"
#endif
#ifdef PBI_BB
#include "pbi_bb.h"
#endif
#ifdef PBI_XLD
#include "pbi_xld.h"
#endif
#ifdef XEP80_EMULATION
#include "xep80.h"
#endif
#define SAVE_VERSION_NUMBER 6
#if defined(MEMCOMPR)
static gzFile *mem_open(const char *name, const char *mode);
static int mem_close(gzFile *stream);
static size_t mem_read(void *buf, size_t len, gzFile *stream);
static size_t mem_write(const void *buf, size_t len, gzFile *stream);
#define GZOPEN(X, Y) mem_open(X, Y)
#define GZCLOSE(X) mem_close(X)
#define GZREAD(X, Y, Z) mem_read(Y, Z, X)
#define GZWRITE(X, Y, Z) mem_write(Y, Z, X)
#undef GZERROR
#elif defined(HAVE_LIBZ) /* above MEMCOMPR, below HAVE_LIBZ */
#define GZOPEN(X, Y) gzopen(X, Y)
#define GZCLOSE(X) gzclose(X)
#define GZREAD(X, Y, Z) gzread(X, Y, Z)
#define GZWRITE(X, Y, Z) gzwrite(X, (const voidp) Y, Z)
#define GZERROR(X, Y) gzerror(X, Y)
#else
#define GZOPEN(X, Y) fopen(X, Y)
#define GZCLOSE(X) fclose(X)
#define GZREAD(X, Y, Z) fread(Y, Z, 1, X)
#define GZWRITE(X, Y, Z) fwrite(Y, Z, 1, X)
#undef GZERROR
#define gzFile FILE *
#define Z_OK 0
#endif
static gzFile StateFile = NULL;
static int nFileError = Z_OK;
static void GetGZErrorText(void)
{
#ifdef GZERROR
const char *error = GZERROR(StateFile, &nFileError);
if (nFileError == Z_ERRNO) {
#ifdef HAVE_STRERROR
Log_print("The following general file I/O error occurred:");
Log_print(strerror(errno));
#else
Log_print("A file I/O error occurred");
#endif
return;
}
Log_print("ZLIB returned the following error: %s", error);
#endif /* GZERROR */
Log_print("State file I/O failed.");
}
/* Value is memory location of data, num is number of type to save */
void StateSav_SaveUBYTE(const UBYTE *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
/* Assumption is that UBYTE = 8bits and the pointer passed in refers
directly to the active bits if in a padded location. If not (unlikely)
you'll have to redefine this to save appropriately for cross-platform
compatibility */
if (GZWRITE(StateFile, data, num) == 0)
GetGZErrorText();
}
/* Value is memory location of data, num is number of type to save */
void StateSav_ReadUBYTE(UBYTE *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
if (GZREAD(StateFile, data, num) == 0)
GetGZErrorText();
}
/* Value is memory location of data, num is number of type to save */
void StateSav_SaveUWORD(const UWORD *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
/* UWORDS are saved as 16bits, regardless of the size on this particular
platform. Each byte of the UWORD will be pushed out individually in
LSB order. The shifts here and in the read routines will work for both
LSB and MSB architectures. */
while (num > 0) {
UWORD temp;
UBYTE byte;
temp = *data++;
byte = temp & 0xff;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
temp >>= 8;
byte = temp & 0xff;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
num--;
}
}
/* Value is memory location of data, num is number of type to save */
void StateSav_ReadUWORD(UWORD *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
while (num > 0) {
UBYTE byte1, byte2;
if (GZREAD(StateFile, &byte1, 1) == 0) {
GetGZErrorText();
break;
}
if (GZREAD(StateFile, &byte2, 1) == 0) {
GetGZErrorText();
break;
}
*data++ = (byte2 << 8) | byte1;
num--;
}
}
void StateSav_SaveINT(const int *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
/* INTs are always saved as 32bits (4 bytes) in the file. They can be any size
on the platform however. The sign bit is clobbered into the fourth byte saved
for each int; on read it will be extended out to its proper position for the
native INT size */
while (num > 0) {
UBYTE signbit = 0;
unsigned int temp;
UBYTE byte;
int temp0;
temp0 = *data++;
if (temp0 < 0) {
temp0 = -temp0;
signbit = 0x80;
}
temp = (unsigned int) temp0;
byte = temp & 0xff;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
temp >>= 8;
byte = temp & 0xff;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
temp >>= 8;
byte = temp & 0xff;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
temp >>= 8;
byte = (temp & 0x7f) | signbit;
if (GZWRITE(StateFile, &byte, 1) == 0) {
GetGZErrorText();
break;
}
num--;
}
}
void StateSav_ReadINT(int *data, int num)
{
if (!StateFile || nFileError != Z_OK)
return;
while (num > 0) {
UBYTE signbit = 0;
int temp;
UBYTE byte1, byte2, byte3, byte4;
if (GZREAD(StateFile, &byte1, 1) == 0) {
GetGZErrorText();
break;
}
if (GZREAD(StateFile, &byte2, 1) == 0) {
GetGZErrorText();
break;
}
if (GZREAD(StateFile, &byte3, 1) == 0) {
GetGZErrorText();
break;
}
if (GZREAD(StateFile, &byte4, 1) == 0) {
GetGZErrorText();
break;
}
signbit = byte4 & 0x80;
byte4 &= 0x7f;
temp = (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1;
if (signbit)
temp = -temp;
*data++ = temp;
num--;
}
}
void StateSav_SaveFNAME(const char *filename)
{
UWORD namelen;
#ifdef HAVE_GETCWD
char dirname[FILENAME_MAX];
/* Check to see if file is in application tree, if so, just save as
relative path....*/
getcwd(dirname, FILENAME_MAX);
if (strncmp(filename, dirname, strlen(dirname)) == 0)
/* XXX: check if '/' or '\\' follows dirname in filename? */
filename += strlen(dirname) + 1;
#endif
namelen = strlen(filename);
/* Save the length of the filename, followed by the filename */
StateSav_SaveUWORD(&namelen, 1);
StateSav_SaveUBYTE((const UBYTE *) filename, namelen);
}
void StateSav_ReadFNAME(char *filename)
{
UWORD namelen = 0;
StateSav_ReadUWORD(&namelen, 1);
if (namelen >= FILENAME_MAX) {
Log_print("Filenames of %d characters not supported on this platform", (int) namelen);
return;
}
StateSav_ReadUBYTE((UBYTE *) filename, namelen);
filename[namelen] = 0;
}
int StateSav_SaveAtariState(const char *filename, const char *mode, UBYTE SaveVerbose)
{
UBYTE StateVersion = SAVE_VERSION_NUMBER;
if (StateFile != NULL) {
GZCLOSE(StateFile);
StateFile = NULL;
}
nFileError = Z_OK;
StateFile = GZOPEN(filename, mode);
if (StateFile == NULL) {
Log_print("Could not open %s for state save.", filename);
GetGZErrorText();
return FALSE;
}
if (GZWRITE(StateFile, "ATARI800", 8) == 0) {
GetGZErrorText();
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
StateSav_SaveUBYTE(&StateVersion, 1);
StateSav_SaveUBYTE(&SaveVerbose, 1);
/* The order here is important. Atari800_StateSave must be first because it saves the machine type, and
decisions on what to save/not save are made based off that later in the process */
Atari800_StateSave();
CARTRIDGE_StateSave();
SIO_StateSave();
ANTIC_StateSave();
CPU_StateSave(SaveVerbose);
GTIA_StateSave();
PIA_StateSave();
POKEY_StateSave();
#ifdef XEP80_EMULATION
XEP80_StateSave();
#else
{
int local_xep80_enabled = FALSE;
StateSav_SaveINT(&local_xep80_enabled, 1);
}
#endif /* XEP80_EMULATION */
PBI_StateSave();
#ifdef PBI_MIO
PBI_MIO_StateSave();
#else
{
int local_mio_enabled = FALSE;
StateSav_SaveINT(&local_mio_enabled, 1);
}
#endif /* PBI_MIO */
#ifdef PBI_BB
PBI_BB_StateSave();
#else
{
int local_bb_enabled = FALSE;
StateSav_SaveINT(&local_bb_enabled, 1);
}
#endif /* PBI_BB */
#ifdef PBI_XLD
PBI_XLD_StateSave();
#else
{
int local_xld_enabled = FALSE;
StateSav_SaveINT(&local_xld_enabled, 1);
}
#endif /* PBI_XLD */
#ifdef DREAMCAST
DCStateSave();
#endif
if (GZCLOSE(StateFile) != 0) {
StateFile = NULL;
return FALSE;
}
StateFile = NULL;
if (nFileError != Z_OK)
return FALSE;
return TRUE;
}
int StateSav_ReadAtariState(const char *filename, const char *mode)
{
char header_string[8];
UBYTE StateVersion = 0; /* The version of the save file */
UBYTE SaveVerbose = 0; /* Verbose mode means save basic, OS if patched */
if (StateFile != NULL) {
GZCLOSE(StateFile);
StateFile = NULL;
}
nFileError = Z_OK;
StateFile = GZOPEN(filename, mode);
if (StateFile == NULL) {
Log_print("Could not open %s for state read.", filename);
GetGZErrorText();
return FALSE;
}
if (GZREAD(StateFile, header_string, 8) == 0) {
GetGZErrorText();
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
if (memcmp(header_string, "ATARI800", 8) != 0) {
Log_print("This is not an Atari800 state save file.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
if (GZREAD(StateFile, &StateVersion, 1) == 0
|| GZREAD(StateFile, &SaveVerbose, 1) == 0) {
Log_print("Failed read from Atari state file.");
GetGZErrorText();
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
if (StateVersion != SAVE_VERSION_NUMBER && StateVersion < 3) {
Log_print("Cannot read this state file because it is an incompatible version.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
Atari800_StateRead();
if (StateVersion >= 4) {
CARTRIDGE_StateRead();
SIO_StateRead();
}
ANTIC_StateRead();
CPU_StateRead(SaveVerbose, StateVersion);
GTIA_StateRead();
PIA_StateRead();
POKEY_StateRead();
if (StateVersion >= 6) {
#ifdef XEP80_EMULATION
XEP80_StateRead();
#else
int local_xep80_enabled;
StateSav_ReadINT(&local_xep80_enabled,1);
if (local_xep80_enabled) {
Log_print("Cannot read this state file because this version does not support XEP80.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
#endif /* XEP80_EMULATION */
PBI_StateRead();
#ifdef PBI_MIO
PBI_MIO_StateRead();
#else
{
int local_mio_enabled;
StateSav_ReadINT(&local_mio_enabled,1);
if (local_mio_enabled) {
Log_print("Cannot read this state file because this version does not support MIO.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
}
#endif /* PBI_MIO */
#ifdef PBI_BB
PBI_BB_StateRead();
#else
{
int local_bb_enabled;
StateSav_ReadINT(&local_bb_enabled,1);
if (local_bb_enabled) {
Log_print("Cannot read this state file because this version does not support the Black Box.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
}
#endif /* PBI_BB */
#ifdef PBI_XLD
PBI_XLD_StateRead();
#else
{
int local_xld_enabled;
StateSav_ReadINT(&local_xld_enabled,1);
if (local_xld_enabled) {
Log_print("Cannot read this state file because this version does not support the 1400XL/1450XLD.");
GZCLOSE(StateFile);
StateFile = NULL;
return FALSE;
}
}
#endif /* PBI_XLD */
}
#ifdef DREAMCAST
DCStateRead();
#endif
GZCLOSE(StateFile);
StateFile = NULL;
if (nFileError != Z_OK)
return FALSE;
return TRUE;
}
/* hack to compress in memory before writing
* - for DREAMCAST only
* - 2 reasons for this:
* - use bzip2 instead of zip: better compression ratio (the DC VMUs are small)
* - write in DC specific file format to provide icon and description
*/
#ifdef MEMCOMPR
static char * plainmembuf;
static unsigned int plainmemoff;
static char * comprmembuf;
#define OM_READ 1
#define OM_WRITE 2
static int openmode;
static unsigned int unclen;
static char savename[FILENAME_MAX];
#define HDR_LEN 640
#define ALLOC_LEN 210000
/* replacement for GZOPEN */
static gzFile *mem_open(const char *name, const char *mode)
{
if (*mode == 'w') {
/* open for write (save) */
openmode = OM_WRITE;
strcpy(savename, name); /* remember name */
plainmembuf = Util_malloc(ALLOC_LEN);
plainmemoff = 0; /*HDR_LEN;*/
return (gzFile *) plainmembuf;
}
else {
/* open for read (read) */
FILE *f;
size_t len;
openmode = OM_READ;
unclen = ALLOC_LEN;
f = fopen(name, mode);
if (f == NULL)
return NULL;
plainmembuf = Util_malloc(ALLOC_LEN);
comprmembuf = Util_malloc(ALLOC_LEN);
len = fread(comprmembuf, 1, ALLOC_LEN, f);
fclose(f);
/* XXX: does DREAMCAST's fread return ((size_t) -1) ? */
if (len != 0
&& BZ2_bzBuffToBuffDecompress(plainmembuf, &unclen, comprmembuf + HDR_LEN, len - HDR_LEN, 1, 0) == BZ_OK) {
#ifdef DEBUG
printf("decompress: old len %lu, new len %lu\n",
(unsigned long) len - 1024, (unsigned long) unclen);
#endif
free(comprmembuf);
plainmemoff = 0;
return (gzFile *) plainmembuf;
}
free(comprmembuf);
free(plainmembuf);
return NULL;
}
}
/* replacement for GZCLOSE */
static int mem_close(gzFile *stream)
{
int status = -1;
unsigned int comprlen = ALLOC_LEN - HDR_LEN;
if (openmode != OM_WRITE) {
/* was opened for read */
free(plainmembuf);
return 0;
}
comprmembuf = Util_malloc(ALLOC_LEN);
if (BZ2_bzBuffToBuffCompress(comprmembuf + HDR_LEN, &comprlen, plainmembuf, plainmemoff, 9, 0, 0) == BZ_OK) {
FILE *f;
f = fopen(savename, "wb");
if (f != NULL) {
char icon[32 + 512];
#ifdef DEBUG
printf("mem_close: plain len %lu, compr len %lu\n",
(unsigned long) plainmemoff, (unsigned long) comprlen);
#endif
memcpy(icon, palette, 32);
memcpy(icon + 32, bitmap, 512);
ndc_vmu_create_vmu_header(comprmembuf, "Atari800DC",
"Atari800DC " A800DCVERASC " saved state",
comprlen, icon);
comprlen = (comprlen + HDR_LEN + 511) & ~511;
ndc_vmu_do_crc(comprmembuf, comprlen);
status = (fwrite(comprmembuf, 1, comprlen, f) == comprlen) ? 0 : -1;
status |= fclose(f);
#ifdef DEBUG
if (status != 0)
printf("mem_close: fwrite: error!!\n");
#endif
}
}
free(comprmembuf);
free(plainmembuf);
return status;
}
/* replacement for GZREAD */
static size_t mem_read(void *buf, size_t len, gzFile *stream)
{
if (plainmemoff + len > unclen) return 0; /* shouldn't happen */
memcpy(buf, plainmembuf + plainmemoff, len);
plainmemoff += len;
return len;
}
/* replacement for GZWRITE */
static size_t mem_write(const void *buf, size_t len, gzFile *stream)
{
if (plainmemoff + len > ALLOC_LEN) return 0; /* shouldn't happen */
memcpy(plainmembuf + plainmemoff, buf, len);
plainmemoff += len;
return len;
}
#endif /* #ifdef MEMCOMPR */

View File

@@ -1,19 +0,0 @@
#ifndef STATESAV_H_
#define STATESAV_H_
#include "atari.h"
int StateSav_SaveAtariState(const char *filename, const char *mode, UBYTE SaveVerbose);
int StateSav_ReadAtariState(const char *filename, const char *mode);
void StateSav_SaveUBYTE(const UBYTE *data, int num);
void StateSav_SaveUWORD(const UWORD *data, int num);
void StateSav_SaveINT(const int *data, int num);
void StateSav_SaveFNAME(const char *filename);
void StateSav_ReadUBYTE(UBYTE *data, int num);
void StateSav_ReadUWORD(UWORD *data, int num);
void StateSav_ReadINT(int *data, int num);
void StateSav_ReadFNAME(char *filename);
#endif /* STATESAV_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,195 +0,0 @@
/*
* ui.h - Atari user interface definitions
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef UI_H_
#define UI_H_
#include "config.h"
#include <stdio.h> /* FILENAME_MAX */
#include "atari.h"
/* Three legitimate entries to UI module. */
int UI_SelectCartType(int k);
void UI_Run(void);
extern int UI_is_active;
extern int UI_alt_function;
#ifdef CRASH_MENU
extern int UI_crash_code;
extern UWORD UI_crash_address;
extern UWORD UI_crash_afterCIM;
#endif
#define UI_MAX_DIRECTORIES 8
extern char UI_atari_files_dir[UI_MAX_DIRECTORIES][FILENAME_MAX];
extern char UI_saved_files_dir[UI_MAX_DIRECTORIES][FILENAME_MAX];
extern int UI_n_atari_files_dir;
extern int UI_n_saved_files_dir;
#ifdef SDL
void PLATFORM_SetJoystickKey(int joystick, int direction, int value);
void PLATFORM_GetJoystickKeyName(int joystick, int direction, char *buffer, int bufsize);
int GetRawKey(void);
#endif
/* Menu codes for Alt+letter shortcuts.
Store in UI_alt_function and put AKEY_UI in INPUT_key_code. */
#define UI_MENU_DISK 0
#define UI_MENU_CARTRIDGE 1
#define UI_MENU_RUN 2
#define UI_MENU_SYSTEM 3
#define UI_MENU_SOUND 4
#define UI_MENU_SOUND_RECORDING 5
#define UI_MENU_DISPLAY 6
#define UI_MENU_SETTINGS 7
#define UI_MENU_SAVESTATE 8
#define UI_MENU_LOADSTATE 9
#define UI_MENU_PCX 10
#define UI_MENU_PCXI 11
#define UI_MENU_BACK 12
#define UI_MENU_RESETW 13
#define UI_MENU_RESETC 14
#define UI_MENU_MONITOR 15
#define UI_MENU_ABOUT 16
#define UI_MENU_EXIT 17
#define UI_MENU_CASSETTE 18
/* Structure of menu item. Each menu is just an array of items of this structure
terminated by UI_MENU_END */
typedef struct
{
UWORD flags; /* Flags, see values below */
SWORD retval; /* Value returned by Select when this item is selected */
/* < 0 means that item is strictly informative and cannot be selected */
char *prefix; /* Text to prepend the item */
char *item; /* Main item text */
const char *suffix; /* Optional text to show after the item text (e.g. key shortcut) */
/* or (if (flags & UI_ITEM_TIP) != 0) "tooltip" */
} UI_tMenuItem;
/* The following are item types, mutually exclusive. */
#define UI_ITEM_HIDDEN 0x00 /* Item does not appear in the menu */
#define UI_ITEM_ACTION 0x01 /* Item invokes an action */
#define UI_ITEM_CHECK 0x02 /* Item represents a boolean value */
#define UI_ITEM_FILESEL 0x03 /* Item invokes file/directory selection */
#define UI_ITEM_SUBMENU 0x04 /* Item opens a submenu */
/* UI_ITEM_CHECK means that the value of UI_ITEM_CHECKED is shown.
UI_ITEM_FILESEL and UI_ITEM_SUBMENU are just for optional decorations,
so the user knows what happens when he/she selects this item. */
#define UI_ITEM_TYPE 0x0f
/* The following are bit masks and should be combined with one of the above item types. */
#define UI_ITEM_CHECKED 0x10 /* The boolean value for UI_ITEM_CHECK is true */
#define UI_ITEM_TIP 0x20 /* suffix is shown when the item is selected rather than on its right */
#if defined(_WIN32_WCE) || defined(DREAMCAST)
/* No function keys nor Alt+letter on Windows CE, Sega DC */
#define UI_MENU_ACCEL(keystroke) NULL
#else
#define UI_MENU_ACCEL(keystroke) keystroke
#endif
#define UI_MENU_LABEL(item) { UI_ITEM_ACTION, -1, NULL, item, NULL }
#define UI_MENU_ACTION(retval, item) { UI_ITEM_ACTION, retval, NULL, item, NULL }
#define UI_MENU_ACTION_PREFIX(retval, prefix, item) { UI_ITEM_ACTION, retval, prefix, item, NULL }
#define UI_MENU_ACTION_PREFIX_TIP(retval, prefix, item, tip) { UI_ITEM_ACTION | UI_ITEM_TIP, retval, prefix, item, tip }
#define UI_MENU_ACTION_ACCEL(retval, item, keystroke) { UI_ITEM_ACTION, retval, NULL, item, UI_MENU_ACCEL(keystroke) }
#define UI_MENU_ACTION_TIP(retval, item, tip) { UI_ITEM_ACTION | UI_ITEM_TIP, retval, NULL, item, tip }
#define UI_MENU_CHECK(retval, item) { UI_ITEM_CHECK, retval, NULL, item, NULL }
#define UI_MENU_FILESEL(retval, item) { UI_ITEM_FILESEL, retval, NULL, item, NULL }
#define UI_MENU_FILESEL_PREFIX(retval, prefix, item) { UI_ITEM_FILESEL, retval, prefix, item, NULL }
#define UI_MENU_FILESEL_PREFIX_TIP(retval, prefix, item, tip) { UI_ITEM_FILESEL | UI_ITEM_TIP, retval, prefix, item, tip }
#define UI_MENU_FILESEL_ACCEL(retval, item, keystroke) { UI_ITEM_FILESEL, retval, NULL, item, UI_MENU_ACCEL(keystroke) }
#define UI_MENU_FILESEL_TIP(retval, item, tip) { UI_ITEM_FILESEL | UI_ITEM_TIP, retval, NULL, item, tip }
#define UI_MENU_SUBMENU(retval, item) { UI_ITEM_SUBMENU, retval, NULL, item, NULL }
#define UI_MENU_SUBMENU_SUFFIX(retval, item, suffix) { UI_ITEM_SUBMENU, retval, NULL, item, suffix }
#define UI_MENU_SUBMENU_ACCEL(retval, item, keystroke) { UI_ITEM_SUBMENU, retval, NULL, item, UI_MENU_ACCEL(keystroke) }
#define UI_MENU_END { UI_ITEM_HIDDEN, 0, NULL, NULL, NULL }
/* UI driver entry prototypes */
/* Select provides simple selection from menu.
title can be used as a caption.
If (flags & UI_SELECT_POPUP) != 0 the menu is a popup menu.
default_item is initially selected item (not item # but rather retval from menu structure).
menu is array of items of type UI_tMenuItem, must be termintated by UI_MENU_END.
If seltype is non-null, it is used to return selection type (see UI_USER_* below).
UI_USER_DRAG_UP and UI_USER_DRAG_DOWN are returned only if (flags & UI_SELECT_DRAG) != 0.
Returned is retval of the selected item or -1 if the user cancelled selection,
or -2 if the user pressed "magic key" (Tab). */
typedef int (*UI_fnSelect)(const char *title, int flags, int default_item, const UI_tMenuItem *menu, int *seltype);
/* SelectInt returns an integer chosen by the user from the range min_value..max_value.
default_value is the initial selection and the value returned if the selection is cancelled. */
typedef int (*UI_fnSelectInt)(int default_value, int min_value, int max_value);
/* EditString provides string input. pString is shown initially and can be modified by the user.
It won't exceed nSize characters, including NUL. Note that pString may be modified even
when the user pressed Esc. */
typedef int (*UI_fnEditString)(const char *title, char *string, int size);
/* GetSaveFilename and GetLoadFilename return fully qualified file name via pFilename.
pDirectories are "favourite" directories (there are nDirectories of them).
Selection starts in the directory of the passed pFilename (i.e. pFilename must be initialized)
or (if pFilename[0] == '\0') in the first "favourite" directory. */
typedef int (*UI_fnGetSaveFilename)(char *filename, char directories[][FILENAME_MAX], int n_directories);
typedef int (*UI_fnGetLoadFilename)(char *filename, char directories[][FILENAME_MAX], int n_directories);
/* GetDirectoryPath is a directory browser */
typedef int (*UI_fnGetDirectoryPath)(char *directory);
/* Message is just some kind of MessageBox */
typedef void (*UI_fnMessage)(const char *message, int waitforkey);
/* InfoScreen displays a "long" message.
Caution: lines in pMessage should be ended with '\0', the message should be terminated with '\n'. */
typedef void (*UI_fnInfoScreen)(const char *title, const char *message);
/* Init is called to initialize driver every time UI code is executed.
Driver must be protected against multiple inits. */
typedef void (*UI_fnInit)(void);
/* Bit masks for flags */
#define UI_SELECT_POPUP 0x01
#define UI_SELECT_DRAG 0x02
/* Values returned via seltype */
#define UI_USER_SELECT 1
#define UI_USER_TOGGLE 2
#define UI_USER_DELETE 3
#define UI_USER_DRAG_UP 4
#define UI_USER_DRAG_DOWN 5
typedef struct
{
UI_fnSelect fSelect;
UI_fnSelectInt fSelectInt;
UI_fnEditString fEditString;
UI_fnGetSaveFilename fGetSaveFilename;
UI_fnGetLoadFilename fGetLoadFilename;
UI_fnGetDirectoryPath fGetDirectoryPath;
UI_fnMessage fMessage;
UI_fnInfoScreen fInfoScreen;
UI_fnInit fInit;
} UI_tDriver;
/* Current UI driver. Port can override it and set pointer to port
specific driver */
extern UI_tDriver *UI_driver;
#endif /* UI_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
#ifndef UI_BASIC_H_
#define UI_BASIC_H_
#include "ui.h"
/* "Basic" UI driver. Always present and guaranteed to work. Override
driver may call into this one to implement filtering */
extern UI_tDriver UI_BASIC_driver;
/* for Windows CE and Dreamcast */
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
int UI_BASIC_OnScreenKeyboard(const char *title, int layout);
/* layout must be one of MACHINE_* values (see atari.h)
or -1 for base keyboard with no function keys */
#endif
/* used only in the Dreamcast port */
extern const unsigned char UI_BASIC_key_to_ascii[256];
#endif /* UI_BASIC_H_ */

View File

@@ -1,419 +0,0 @@
/*
* util.c - utility functions
*
* Copyright (c) 2005 Piotr Fusik
* Copyright (c) 2005 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
*
* Atari800 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.
*
* Atari800 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 Atari800; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
/* suppress -ansi -pedantic warning for fdopen: */
#ifdef __STRICT_ANSI__
#undef __STRICT_ANSI__
#include <stdio.h>
#define __STRICT_ANSI__ 1
#else
#include <stdio.h>
#endif /* __STRICT_ANSI__ */
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#include "atari.h"
#include "util.h"
int Util_chrieq(char c1, char c2)
{
switch (c1 ^ c2) {
case 0x00:
return TRUE;
case 0x20:
return (c1 >= 'A' && c1 <= 'Z') || (c1 >= 'a' && c1 <= 'z');
default:
return FALSE;
}
}
#ifdef __STRICT_ANSI__
/*
** STRICMP.C - Comapres strings, case-insensitive.
**
** public domain by Bob Stout
**
*/
/* from http://c.snippets.org/code/stricmp.c */
int Util_stricmp(const char *str1, const char *str2)
{
int retval = 0;
while (1)
{
retval = tolower(*str1++) - tolower(*str2++);
if (retval)
break;
if (*str1 && *str2)
continue;
else break;
}
return retval;
}
#endif
char *Util_stpcpy(char *dest, const char *src)
{
size_t len = strlen(src);
memcpy(dest, src, len + 1);
return dest + len;
}
#ifndef HAVE_STRNCPY
char *Util_strncpy(char *dest, const char *src, size_t size) {
while (size-- > 0) {
if ((*dest++ = *src++) == '\0')
break;
}
while (size-- > 0)
*dest++ = '\0';
return dest;
}
#endif
char *safe_strncpy(char *buffer, const char *source, int bufsize)
{
if (buffer == NULL) return NULL;
if (bufsize > 0) {
strncpy(buffer, source != NULL ? source : "", bufsize);
buffer[bufsize-1] = '\0';
}
return buffer;
}
char *Util_strlcpy(char *dest, const char *src, size_t size)
{
Util_strncpy(dest, src, size);
dest[size - 1] = '\0';
return dest;
}
char *Util_strupper(char *s)
{
char *p;
for (p = s; *p != '\0'; p++)
if (*p >= 'a' && *p <= 'z')
*p += 'A' - 'a';
return s;
}
char *Util_strlower(char *s)
{
char *p;
for (p = s; *p != '\0'; p++)
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
return s;
}
void Util_chomp(char *s)
{
int len;
len = strlen(s);
if (len >= 2 && s[len - 1] == '\n' && s[len - 2] == '\r')
s[len - 2] = '\0';
else if (len >= 1 && (s[len - 1] == '\n' || s[len - 1] == '\r'))
s[len - 1] = '\0';
}
void Util_trim(char *s)
{
char *p = s;
char *q;
/* skip leading whitespace */
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
p++;
/* now p points at the first non-whitespace character */
if (*p == '\0') {
/* only whitespace */
*s = '\0';
return;
}
q = s + strlen(s);
/* skip trailing whitespace */
/* we have found p < q such that *p is non-whitespace,
so this loop terminates with q >= p */
do
q--;
while (*q == ' ' || *q == '\t' || *q == '\r' || *q == '\n');
/* now q points at the last non-whitespace character */
/* cut off trailing whitespace */
*++q = '\0';
/* move to string */
memmove(s, p, q + 1 - p);
}
int Util_sscandec(const char *s)
{
int result;
if (*s == '\0')
return -1;
result = 0;
for (;;) {
if (*s >= '0' && *s <= '9')
result = 10 * result + *s - '0';
else if (*s == '\0')
return result;
else
return -1;
s++;
}
}
int Util_sscanhex(const char *s)
{
int result;
if (*s == '\0')
return -1;
result = 0;
for (;;) {
if (*s >= '0' && *s <= '9')
result = 16 * result + *s - '0';
else if (*s >= 'A' && *s <= 'F')
result = 16 * result + *s - 'A' + 10;
else if (*s >= 'a' && *s <= 'f')
result = 16 * result + *s - 'a' + 10;
else if (*s == '\0')
return result;
else
return -1;
s++;
}
}
int Util_sscanbool(const char *s)
{
if (*s == '0' && s[1] == '\0')
return 0;
if (*s == '1' && s[1] == '\0')
return 1;
return -1;
}
void *Util_malloc(size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL) {
Atari800_Exit(FALSE);
printf("Fatal error: out of memory\n");
exit(1);
}
return ptr;
}
void *Util_realloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
if (ptr == NULL) {
Atari800_Exit(FALSE);
printf("Fatal error: out of memory\n");
exit(1);
}
return ptr;
}
char *Util_strdup(const char *s)
{
/* don't use strdup(): it is unavailable on WinCE */
size_t size = strlen(s) + 1;
char *ptr = (char *) Util_malloc(size);
memcpy(ptr, s, size); /* faster than strcpy(ptr, s) */
return ptr;
}
void Util_splitpath(const char *path, char *dir_part, char *file_part)
{
const char *p;
/* find the last Util_DIR_SEP_CHAR except the last character */
for (p = path + strlen(path) - 2; p >= path; p--) {
if (*p == Util_DIR_SEP_CHAR
#ifdef DIR_SEP_BACKSLASH
/* on DOSish systems slash can be also used as a directory separator */
|| *p == '/'
#endif
) {
if (dir_part != NULL) {
int len = p - path;
if (p == path || (p == path + 2 && path[1] == ':'))
/* root dir: include Util_DIR_SEP_CHAR in dir_part */
len++;
memcpy(dir_part, path, len);
dir_part[len] = '\0';
}
if (file_part != NULL)
strcpy(file_part, p + 1);
return;
}
}
/* no Util_DIR_SEP_CHAR: current dir */
if (dir_part != NULL)
dir_part[0] = '\0';
if (file_part != NULL)
strcpy(file_part, path);
}
void Util_catpath(char *result, const char *path1, const char *path2)
{
#ifdef HAVE_SNPRINTF
snprintf(result, FILENAME_MAX,
#else
sprintf(result,
#endif
path1[0] == '\0' || path2[0] == Util_DIR_SEP_CHAR || path1[strlen(path1) - 1] == Util_DIR_SEP_CHAR
#ifdef DIR_SEP_BACKSLASH
|| path2[0] == '/' || path1[strlen(path1) - 1] == '/'
#endif
? "%s%s" : "%s" Util_DIR_SEP_STR "%s", path1, path2);
}
int Util_fileexists(const char *filename)
{
FILE *fp;
fp = fopen(filename, "rb");
if (fp == NULL)
return FALSE;
fclose(fp);
return TRUE;
}
#ifdef WIN32
int Util_direxists(const char *filename)
{
DWORD attr;
#ifdef UNICODE
WCHAR wfilename[FILENAME_MAX];
if (MultiByteToWideChar(CP_ACP, 0, filename, -1, wfilename, FILENAME_MAX) <= 0)
return FALSE;
attr = GetFileAttributes(wfilename);
#else
attr = GetFileAttributes(filename);
#endif /* UNICODE */
if (attr == 0xffffffff)
return FALSE;
#ifdef _WIN32_WCE
/* WinCE: Make sure user does not up-dir from the root */
if (*filename == 0)
return FALSE;
#endif
return (attr & FILE_ATTRIBUTE_DIRECTORY) ? TRUE : FALSE;
}
#elif defined(HAVE_STAT)
int Util_direxists(const char *filename)
{
struct stat filestatus;
return stat(filename, &filestatus) == 0 && (filestatus.st_mode & S_IFDIR);
}
#else
int Util_direxists(const char *filename)
{
return TRUE;
}
#endif /* defined(HAVE_STAT) */
int Util_flen(FILE *fp)
{
fseek(fp, 0, SEEK_END);
return (int) ftell(fp);
}
/* Creates a file that does not exist and fills in filename with its name.
filename must point to FILENAME_MAX characters buffer which doesn't need
to be initialized. */
FILE *Util_uniqopen(char *filename, const char *mode)
{
/* We cannot simply call tmpfile(), because we don't want the file
to be deleted when we close it, and we need the filename. */
#if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN)
/* this is the only implementation without a race condition */
strcpy(filename, "a8XXXXXX");
/* mkstemp() modifies the 'X'es and returns an open descriptor */
return fdopen(mkstemp(filename), mode);
#elif defined(HAVE_TMPNAM)
/* tmpnam() is better than mktemp(), because it creates filenames
in system's temporary directory. It is also more portable. */
return fopen(tmpnam(filename), mode);
#elif defined(HAVE_MKTEMP)
strcpy(filename, "a8XXXXXX");
/* mktemp() modifies the 'X'es and returns filename */
return fopen(mktemp(filename), mode);
#else
/* Roll-your-own */
int no;
for (no = 0; no < 1000000; no++) {
sprintf(filename, "a8%06d", no);
if (!Util_fileexists(filename))
return fopen(filename, mode);
}
return NULL;
#endif
}
#if defined(WIN32) && defined(UNICODE)
int Util_unlink(const char *filename)
{
WCHAR wfilename[FILENAME_MAX];
#ifdef _WIN32_WCE
char cwd[FILENAME_MAX];
char fullfilename[FILENAME_MAX];
if (filename[0] != '\\' && filename[0] != '/') {
getcwd(cwd, FILENAME_MAX);
Util_catpath(fullfilename, cwd, filename);
if (MultiByteToWideChar(CP_ACP, 0, fullfilename, -1, wfilename, FILENAME_MAX) <= 0)
return -1;
}
else
#endif
if (MultiByteToWideChar(CP_ACP, 0, filename, -1, wfilename, FILENAME_MAX) <= 0)
return -1;
return (DeleteFile(wfilename) != 0) ? 0 : -1;
}
#elif defined(WIN32) && !defined(UNICODE)
int Util_unlink(const char *filename)
{
return (DeleteFile(filename) != 0) ? 0 : -1;
}
#endif /* defined(WIN32) && defined(UNICODE) */

View File

@@ -1,178 +0,0 @@
#ifndef UTIL_H_
#define UTIL_H_
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef WIN32
#include <windows.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
/* String functions ------------------------------------------------------ */
/* Returns TRUE if the characters are equal or represent the same letter
in different case. */
int Util_chrieq(char c1, char c2);
#ifdef __STRICT_ANSI__
/* Returns a positive integer if str1>str2, negative if str1<str2
* 0 if str1 == str2, case insensitive */
int Util_stricmp(const char *str1, const char *str2);
#elif defined(WIN32)
#define Util_stricmp _stricmp
#elif defined(HAVE_STRCASECMP)
#define Util_stricmp strcasecmp
#else
#define Util_stricmp stricmp
#endif
/* Same as stpcpy() in some C libraries: copies src to dest
and returns a pointer to the trailing NUL in dest. */
char *Util_stpcpy(char *dest, const char *src);
/* NestedVM strncpy from newlib has a bug */
#ifdef HAVE_STRNCPY
#define Util_strncpy strncpy
#else
char *Util_strncpy(char *dest, const char *src, size_t size);
#endif
/* Same as strlcpy() in some C libraries: copies src to dest
and terminates the string. Never writes more than size characters
to dest (the result may be truncated). Returns dest. */
char *Util_strlcpy(char *dest, const char *src, size_t size);
/* Modifies the string to uppercase and returns it. */
char *Util_strupper(char *s);
/* Modifies the string to lowercase and returns it. */
char *Util_strlower(char *s);
/* Similar to Perl's chomp(): removes trailing LF, CR or CR/LF. */
void Util_chomp(char *s);
/* Similar to Basic's trim(): removes leading and trailing whitespace. */
void Util_trim(char *s);
/* Converts the string to a non-negative integer and returns it.
The string must represent the number and nothing else.
-1 indicates an error. */
int Util_sscandec(const char *s);
/* Likewise, but parses hexadecimal numbers. */
int Util_sscanhex(const char *s);
/* Likewise, but allows only 0 and 1. */
int Util_sscanbool(const char *s);
/* safe_strncpy guarantees that the dest. buffer ends with '\0' */
char *safe_strncpy(char *, const char *, int);
/* Memory management ----------------------------------------------------- */
/* malloc() with out-of-memory checking. Never returns NULL. */
void *Util_malloc(size_t size);
/* realloc() with out-of-memory checking. Never returns NULL. */
void *Util_realloc(void *ptr, size_t size);
/* strdup() with out-of-memory checking. Never returns NULL. */
char *Util_strdup(const char *s);
/* Filenames ------------------------------------------------------------- */
/* I assume here that '\n' is not valid in filenames,
at least not as their first character. */
#define Util_FILENAME_NOT_SET "\n"
#define Util_filenamenotset(filename) ((filename)[0] == '\n')
#ifdef DIR_SEP_BACKSLASH
#define Util_DIR_SEP_CHAR '\\'
#define Util_DIR_SEP_STR "\\"
#else
#define Util_DIR_SEP_CHAR '/'
#define Util_DIR_SEP_STR "/"
#endif
/* Splits a filename into directory part and file part. */
/* dir_part or file_part may be NULL. */
void Util_splitpath(const char *path, char *dir_part, char *file_part);
/* Concatenates file paths.
Places directory separator char between paths, unless path1 is empty
or ends with the separator char, or path2 starts with the separator char. */
void Util_catpath(char *result, const char *path1, const char *path2);
/* File I/O -------------------------------------------------------------- */
/* Returns TRUE if the specified file exists. */
int Util_fileexists(const char *filename);
/* Returns TRUE if the specified directory exists. */
int Util_direxists(const char *filename);
/* Rewinds the stream to its beginning. */
#ifdef HAVE_REWIND
#define Util_rewind(fp) rewind(fp)
#else
#define Util_rewind(fp) fseek(fp, 0, SEEK_SET)
#endif
/* Returns the length of an open stream.
May change the current position. */
int Util_flen(FILE *fp);
/* Deletes a file, returns 0 on success, -1 on failure. */
#ifdef WIN32
int Util_unlink(const char *filename);
#define HAVE_UTIL_UNLINK
#elif defined(HAVE_UNLINK)
#define Util_unlink unlink
#define HAVE_UTIL_UNLINK
#endif /* defined(HAVE_UNLINK) */
/* Creates a file that does not exist and fills in filename with its name. */
FILE *Util_uniqopen(char *filename, const char *mode);
/* Support for temporary files.
Util_tmpbufdef() defines storage for names of temporary files, if necessary.
Example use:
Util_tmpbufdef(static, mytmpbuf[4]) // four buffers with "static" storage
Util_fopen() opens a *non-temporary* file and marks tmpbuf
as *not containing* name of a temporary file.
Util_tmpopen() creates a temporary file with "wb+" mode.
Util_fclose() closes a file. If it was temporary, it gets deleted.
There are 3 implementations of the above:
- one that uses tmpfile() (preferred)
- one that stores names of temporary files and deletes them when they
are closed
- one that creates unique files but doesn't delete them
because Util_unlink is not available
*/
#ifdef HAVE_TMPFILE
#define Util_tmpbufdef(modifier, def)
#define Util_fopen(filename, mode, tmpbuf) fopen(filename, mode)
#define Util_tmpopen(tmpbuf) tmpfile()
#define Util_fclose(fp, tmpbuf) fclose(fp)
#elif defined(HAVE_UTIL_UNLINK)
#define Util_tmpbufdef(modifier, def) modifier char def [FILENAME_MAX];
#define Util_fopen(filename, mode, tmpbuf) (tmpbuf[0] = '\0', fopen(filename, mode))
#define Util_tmpopen(tmpbuf) Util_uniqopen(tmpbuf, "wb+")
#define Util_fclose(fp, tmpbuf) (fclose(fp), tmpbuf[0] != '\0' && Util_unlink(tmpbuf))
#else
/* if we can't delete the created file, leave it to the user */
#define Util_tmpbufdef(modifier, def)
#define Util_fopen(filename, mode, tmpbuf) fopen(filename, mode)
#define Util_tmpopen(tmpbuf) Util_uniqopen(NULL, "wb+")
#define Util_fclose(fp, tmpbuf) fclose(fp)
#endif
#endif /* UTIL_H_ */

View File

@@ -1,470 +0,0 @@
/* License note by perry_m:
Permission has been granted by the authors Mike Coates and Tom Haukap
to distribute this file under the terms of the GNU GPL license of Atari800.
The original version written by Mike Coates is from MAME.
This extensively modified version with new samples and mixing written
by Tom Haukap is from PinMAME.
I have also made modifications to this file for use in Atari800 and
allow any modifications to be distributed under any of the licenses
of Atari800, MAME and PinMAME. */
/**************************************************************************
Votrax SC-01 Emulator
Mike@Dissfulfils.co.uk
Tom.Haukap@t-online.de
modified for Atari800 by perry_m@fastmail.fm
**************************************************************************
Votrax_Start - Start emulation, load samples from Votrax subdirectory
Votrax_Stop - End emulation, free memory used for samples
Votrax_PutByte - Write data to votrax port
Votrax_GetStatus - Return busy status (1 = busy)
**************************************************************************/
#ifdef PBI_DEBUG
#define VERBOSE 1
#endif
#if VERBOSE
#define LOG(x) printf x
#else
#define LOG(x)
#endif
#include "votrax.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
static struct {
int busy;
int actPhoneme;
int actIntonation;
struct Votrax_interface *intf;
SWORD* pActPos;
int iRemainingSamples;
SWORD *lpBuffer;
SWORD* pBufferPos;
int iSamplesInBuffer;
int iDelay; /* a count of samples to output '0' in a Delay state */
} votraxsc01_locals;
#define INT16 SWORD
#define UINT16 UWORD
#include "vtxsmpls.inc"
#if VERBOSE
static const char *PhonemeNames[65] =
{
"EH3","EH2","EH1","PA0","DT" ,"A2" ,"A1" ,"ZH",
"AH2","I3" ,"I2" ,"I1" ,"M" ,"N" ,"B" ,"V",
"CH" ,"SH" ,"Z" ,"AW1","NG" ,"AH1","OO1","OO",
"L" ,"K" ,"J" ,"H" ,"G" ,"F" ,"D" ,"S",
"A" ,"AY" ,"Y1" ,"UH3","AH" ,"P" ,"O" ,"I",
"U" ,"Y" ,"T" ,"R" ,"E" ,"W" ,"AE" ,"AE1",
"AW2","UH2","UH1","UH" ,"O2" ,"O1" ,"IU" ,"U1",
"THV","TH" ,"ER" ,"EH" ,"E1" ,"AW" ,"PA1","STOP",
0
};
#endif
/* phoneme types*/
#define PT_NS 0
#define PT_V 1
#define PT_VF 2
#define PT_F 3
#define PT_N 4
#define PT_VS 5
#define PT_FS 6
static int sample_rate[4] = {22050, 22050, 22050, 22050};
/* converts milliseconds to a count of samples */
static int time_to_samples(int ms)
{
return sample_rate[votraxsc01_locals.actIntonation]*ms/1000;
}
static void PrepareVoiceData(int nextPhoneme, int nextIntonation)
{
int iNextRemainingSamples;
SWORD *pNextPos, *lpHelp;
int iFadeOutSamples;
int iFadeOutPos;
int iFadeInSamples;
int iFadeInPos;
int doMix;
/* used only for SecondStart phonemes */
int AdditionalSamples;
/* dwCount is the length of samples to produce in ms from iLengthms */
int dwCount, i;
SWORD data;
AdditionalSamples = 0;
/* some phonenemes have a SecondStart */
if ( PhonemeData[votraxsc01_locals.actPhoneme].iType>=PT_VS && votraxsc01_locals.actPhoneme!=nextPhoneme ) {
AdditionalSamples = PhonemeData[votraxsc01_locals.actPhoneme].iSecondStart;
}
if ( PhonemeData[nextPhoneme].iType>=PT_VS ) {
/* 'stop phonemes' will stop playing until the next phoneme is sent*/
votraxsc01_locals.iRemainingSamples = 0;
return;
}
/* length of samples to produce*/
dwCount = time_to_samples(PhonemeData[nextPhoneme].iLengthms);
votraxsc01_locals.iSamplesInBuffer = dwCount+AdditionalSamples;
if ( AdditionalSamples )
memcpy(votraxsc01_locals.lpBuffer, PhonemeData[votraxsc01_locals.actPhoneme].lpStart[votraxsc01_locals.actIntonation], AdditionalSamples*sizeof(SWORD));
lpHelp = votraxsc01_locals.lpBuffer + AdditionalSamples;
iNextRemainingSamples = 0;
pNextPos = NULL;
iFadeOutSamples = 0;
iFadeOutPos = 0;
iFadeInSamples = 0;
iFadeInPos = 0;
doMix = 0;
/* set up processing*/
if ( PhonemeData[votraxsc01_locals.actPhoneme].sameAs!=PhonemeData[nextPhoneme].sameAs ) {
/* do something, if they are the same all FadeIn/Out values are 0, */
/* the buffer is simply filled with the samples of the new phoneme */
switch ( PhonemeData[votraxsc01_locals.actPhoneme].iType ) {
case PT_NS:
/* "fade" out NS:*/
iFadeOutSamples = time_to_samples(30);
iFadeOutPos = 0;
/* fade in new phoneme*/
iFadeInPos = -time_to_samples(30);
iFadeInSamples = time_to_samples(30);
break;
case PT_V:
case PT_VF:
switch ( PhonemeData[nextPhoneme].iType ){
case PT_F:
case PT_VF:
/* V-->F, V-->VF: fade out 30 ms fade in from 30 ms to 60 ms without mixing*/
iFadeOutPos = 0;
iFadeOutSamples = time_to_samples(30);
iFadeInPos = -time_to_samples(30);
iFadeInSamples = time_to_samples(30);
break;
case PT_N:
/* V-->N: fade out 40 ms fade from 0 ms to 40 ms without mixing*/
iFadeOutPos = 0;
iFadeOutSamples = time_to_samples(40);
iFadeInPos = -time_to_samples(10);
iFadeInSamples = time_to_samples(10);
break;
default:
/* fade out 20 ms, no fade in from 10 ms to 30 ms*/
iFadeOutPos = 0;
iFadeOutSamples = time_to_samples(20);
iFadeInPos = -time_to_samples(0);
iFadeInSamples = time_to_samples(20);
break;
}
break;
case PT_N:
switch ( PhonemeData[nextPhoneme].iType ){
case PT_V:
case PT_VF:
/* N-->V, N-->VF: fade out 30 ms fade in from 10 ms to 50 ms without mixing*/
iFadeOutPos = 0;
iFadeOutSamples = time_to_samples(30);
iFadeInPos = -time_to_samples(10);
iFadeInSamples = time_to_samples(40);
break;
default:
break;
}
case PT_VS:
case PT_FS:
iFadeOutPos = 0;
iFadeOutSamples = PhonemeData[votraxsc01_locals.actPhoneme].iLength[votraxsc01_locals.actIntonation] - PhonemeData[votraxsc01_locals.actPhoneme].iSecondStart;
votraxsc01_locals.pActPos = PhonemeData[votraxsc01_locals.actPhoneme].lpStart[votraxsc01_locals.actIntonation] + PhonemeData[votraxsc01_locals.actPhoneme].iSecondStart;
votraxsc01_locals.iRemainingSamples = iFadeOutSamples;
doMix = 1;
iFadeInPos = -time_to_samples(0);
iFadeInSamples = time_to_samples(0);
break;
default:
/* fade out 30 ms, no fade in*/
iFadeOutPos = 0;
iFadeOutSamples = time_to_samples(20);
iFadeInPos = -time_to_samples(20);
break;
}
if ( !votraxsc01_locals.iDelay ) {
/* this is true if after a stop and a phoneme was sent a second phoneme is sent*/
/* during the delay time of the chip. Ignore the first phoneme data*/
iFadeOutPos = 0;
iFadeOutSamples = 0;
}
}
else {
/* the next one is of the same type as the previous one; continue to use the samples of the last phoneme*/
iNextRemainingSamples = votraxsc01_locals.iRemainingSamples;
pNextPos = votraxsc01_locals.pActPos;
}
for (i=0; i<dwCount; i++)
{
data = 0x00;
/* fade out*/
if ( iFadeOutPos<iFadeOutSamples )
{
double dFadeOut = 1.0;
if ( !doMix )
dFadeOut = 1.0-sin((1.0*iFadeOutPos/iFadeOutSamples)*3.1415/2);
if ( !votraxsc01_locals.iRemainingSamples ) {
votraxsc01_locals.iRemainingSamples = PhonemeData[votraxsc01_locals.actPhoneme].iLength[votraxsc01_locals.actIntonation];
votraxsc01_locals.pActPos = PhonemeData[votraxsc01_locals.actPhoneme].lpStart[votraxsc01_locals.actIntonation];
}
data = (SWORD) (*votraxsc01_locals.pActPos++ * dFadeOut);
votraxsc01_locals.iRemainingSamples--;
iFadeOutPos++;
}
/* fade in or copy*/
if ( iFadeInPos>=0 )
{
double dFadeIn = 1.0;
if ( iFadeInPos<iFadeInSamples ) {
dFadeIn = sin((1.0*iFadeInPos/iFadeInSamples)*3.1415/2);
iFadeInPos++;
}
if ( !iNextRemainingSamples ) {
iNextRemainingSamples = PhonemeData[nextPhoneme].iLength[nextIntonation];
pNextPos = PhonemeData[nextPhoneme].lpStart[nextIntonation];
}
data += (SWORD) (*pNextPos++ * dFadeIn);
iNextRemainingSamples--;
}
iFadeInPos++;
*lpHelp++ = data;
}
votraxsc01_locals.pBufferPos = votraxsc01_locals.lpBuffer;
votraxsc01_locals.pActPos = pNextPos;
votraxsc01_locals.iRemainingSamples = iNextRemainingSamples;
}
void Votrax_PutByte(UBYTE data)
{
int Phoneme, Intonation;
Phoneme = data & 0x3F;
Intonation = (data >> 6)&0x03;
#ifdef VERBOSE
if (!votraxsc01_locals.intf) {
LOG(("Error: votraxsc01_locals.intf not set"));
return;
}
#endif /* VERBOSE */
LOG(("Votrax SC-01: %s at intonation %d\n", PhonemeNames[Phoneme], Intonation));
PrepareVoiceData(Phoneme, Intonation);
if ( votraxsc01_locals.actPhoneme==0x3f )
votraxsc01_locals.iDelay = time_to_samples(20);
if ( !votraxsc01_locals.busy )
{
votraxsc01_locals.busy = 1;
if ( votraxsc01_locals.intf->BusyCallback )
(*votraxsc01_locals.intf->BusyCallback)(votraxsc01_locals.busy);
}
votraxsc01_locals.actPhoneme = Phoneme;
votraxsc01_locals.actIntonation = Intonation;
}
UBYTE Votrax_GetStatus(void)
{
return votraxsc01_locals.busy;
}
void Votrax_Update(int num, SWORD *buffer, int length)
{
int samplesToCopy;
/* if it is a different intonation */
if ( num!=votraxsc01_locals.actIntonation ) {
/* clear buffer */
memset(buffer, 0x00, length*sizeof(SWORD));
return;
}
while ( length ) {
/* Case 1: if in a delay state, output 0's*/
if ( votraxsc01_locals.iDelay ) {
samplesToCopy = (length<=votraxsc01_locals.iDelay)?length:votraxsc01_locals.iDelay;
memset(buffer, 0x00, samplesToCopy*sizeof(SWORD));
buffer += samplesToCopy;
votraxsc01_locals.iDelay -= samplesToCopy;
length -= samplesToCopy; /* missing in the original */
}
/* Case 2: there are no samples left in the buffer */
else if ( votraxsc01_locals.iSamplesInBuffer==0 ) {
if ( votraxsc01_locals.busy ) {
/* busy -> idle */
votraxsc01_locals.busy = 0;
if ( votraxsc01_locals.intf->BusyCallback )
(*votraxsc01_locals.intf->BusyCallback)(votraxsc01_locals.busy);
}
if ( votraxsc01_locals.iRemainingSamples==0 ) {
if ( PhonemeData[votraxsc01_locals.actPhoneme].iType>=PT_VS ) {
votraxsc01_locals.pActPos = PhonemeData[0x3f].lpStart[0];
votraxsc01_locals.iRemainingSamples = PhonemeData[0x3f].iLength[0];
}
else {
votraxsc01_locals.pActPos = PhonemeData[votraxsc01_locals.actPhoneme].lpStart[votraxsc01_locals.actIntonation];
votraxsc01_locals.iRemainingSamples = PhonemeData[votraxsc01_locals.actPhoneme].iLength[votraxsc01_locals.actIntonation];
}
}
/* if there aren't enough remaining, reduce the amount */
samplesToCopy = (length<=votraxsc01_locals.iRemainingSamples)?length:votraxsc01_locals.iRemainingSamples;
memcpy(buffer, votraxsc01_locals.pActPos, samplesToCopy*sizeof(SWORD));
buffer += samplesToCopy;
votraxsc01_locals.pActPos += samplesToCopy;
votraxsc01_locals.iRemainingSamples -= samplesToCopy;
length -= samplesToCopy;
}
/* Case 3: output the samples in the buffer */
else {
samplesToCopy = (length<=votraxsc01_locals.iSamplesInBuffer)?length:votraxsc01_locals.iSamplesInBuffer;
memcpy(buffer, votraxsc01_locals.pBufferPos, samplesToCopy*sizeof(SWORD));
buffer += samplesToCopy;
votraxsc01_locals.pBufferPos += samplesToCopy;
votraxsc01_locals.iSamplesInBuffer -= samplesToCopy;
length -= samplesToCopy;
}
}
}
int Votrax_Start(void *sound_interface)
{
int i, buffer_size;
/* clear local variables */
memset(&votraxsc01_locals, 0x00, sizeof votraxsc01_locals);
/* copy interface */
votraxsc01_locals.intf = (struct Votrax_interface *)sound_interface;
votraxsc01_locals.actPhoneme = 0x3f;
/* find the largest possible size of iSamplesInBuffer */
buffer_size = 0;
for (i = 0; i <= 0x3f; i++) {
int dwCount;
int size;
int AdditionalSamples;
AdditionalSamples = PhonemeData[i].iSecondStart;
dwCount = time_to_samples(PhonemeData[i].iLengthms);
size = dwCount + AdditionalSamples;
if (size > buffer_size) buffer_size = size;
}
votraxsc01_locals.lpBuffer = (SWORD*) Util_malloc(buffer_size*sizeof(SWORD));
PrepareVoiceData(votraxsc01_locals.actPhoneme, votraxsc01_locals.actIntonation);
return 0;
}
void Votrax_Stop(void)
{
if ( votraxsc01_locals.lpBuffer ) {
free(votraxsc01_locals.lpBuffer);
votraxsc01_locals.lpBuffer = NULL;
}
}
int Votrax_Samples(int currentP, int nextP, int cursamples)
{
int AdditionalSamples = 0;
int dwCount;
int delay = 0;
/* some phonemes have a SecondStart */
if ( PhonemeData[currentP].iType>=PT_VS && currentP!=nextP) {
AdditionalSamples = PhonemeData[currentP].iSecondStart;
}
if ( PhonemeData[nextP].iType>=PT_VS ) {
/* 'stop phonemes' will stop playing until the next phoneme is sent*/
/* votraxsc01_locals.iRemainingSamples = 0; */
return cursamples;
}
if (currentP == 0x3f) delay = time_to_samples(20);
/* length of samples to produce*/
dwCount = time_to_samples(PhonemeData[nextP].iLengthms);
return dwCount + AdditionalSamples + delay ;
}
/*
vim:ts=4:sw=4:
*/

View File

@@ -1,23 +0,0 @@
#ifndef VOTRAX_H_
#define VOTRAX_H_
#include "atari.h"
typedef void (*Votrax_BusyCallBack)(int);
struct Votrax_interface
{
int num; /* total number of chips */
Votrax_BusyCallBack BusyCallback; /* callback function when busy signal changes */
};
int Votrax_Start(void *sound_interface);
void Votrax_Stop(void);
void Votrax_PutByte(UBYTE data);
UBYTE Votrax_GetStatus(void);
void Votrax_Update(int num, SWORD *buffer, int length);
int Votrax_Samples(int currentP, int nextP, int cursamples);
#endif /* VOTRAX_H_ */

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