From e71efa3acd608595bf7ba2f796adb49e1d24072d Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Tue, 11 Jun 2013 00:08:15 -0700 Subject: [PATCH] initial source drop, apple2-emul-0.7.4.tar.gz --- .apple2 | 11 + ASM | 15 + AUTHORS | 11 + COPYING | 339 ++++ ChangeLog | 1237 +++++++++++++++ INSTALL | 182 +++ LSM | 16 + Makefile.am | 3 + Makefile.in | 320 ++++ NEWS | 260 ++++ PROBLEMS | 115 ++ README | 408 +++++ README.debugger | 154 ++ TODO | 12 + acinclude.m4 | 12 + aclocal.m4 | 117 ++ configure | 2608 +++++++++++++++++++++++++++++++ configure.in | 35 + disks/Makefile.am | 5 + disks/Makefile.in | 173 +++ disks/README | 22 + disks/blank.dsk.gz | Bin 0 -> 7335 bytes disks/blank.nib.gz | Bin 0 -> 12992 bytes disks/etc.dsk.gz | Bin 0 -> 28592 bytes disks/mystery.dsk.gz | Bin 0 -> 44633 bytes disks/speedtest.dsk.gz | Bin 0 -> 15153 bytes disks/speedtest.txt | 74 + install-sh | 250 +++ missing | 188 +++ mkinstalldirs | 40 + src/Makefile.am | 77 + src/Makefile.in | 433 ++++++ src/apple2.6 | 301 ++++ src/apple2.h | 38 + src/compact.c | 174 +++ src/cpu-supp.c | 88 ++ src/cpu.S | 3348 ++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 131 ++ src/debug.h | 104 ++ src/debug.l-cpp | 901 +++++++++++ src/debugger.c | 1135 ++++++++++++++ src/disk.c | 671 ++++++++ src/disk.h | 67 + src/display.S | 1238 +++++++++++++++ src/font.txt | 1276 +++++++++++++++ src/genfont.c | 115 ++ src/genglue | 5 + src/glue.h | 28 + src/gluepro.h | 75 + src/interface.c | 1229 +++++++++++++++ src/interface.h | 28 + src/joystick.c | 207 +++ src/keys.c | 461 ++++++ src/keys.h | 95 ++ src/memory.S | 977 ++++++++++++ src/misc.c | 745 +++++++++ src/misc.h | 261 ++++ src/opcodes.c | 820 ++++++++++ src/prefs.c | 412 +++++ src/prefs.h | 74 + src/svideo.c | 215 +++ src/video.h | 232 +++ src/vidsup.c | 679 ++++++++ src/xvideo.c | 851 ++++++++++ 64 files changed, 24098 insertions(+) create mode 100644 .apple2 create mode 100644 ASM create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 LSM create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 PROBLEMS create mode 100644 README create mode 100644 README.debugger create mode 100644 TODO create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100755 configure create mode 100644 configure.in create mode 100644 disks/Makefile.am create mode 100644 disks/Makefile.in create mode 100644 disks/README create mode 100644 disks/blank.dsk.gz create mode 100644 disks/blank.nib.gz create mode 100644 disks/etc.dsk.gz create mode 100644 disks/mystery.dsk.gz create mode 100644 disks/speedtest.dsk.gz create mode 100644 disks/speedtest.txt create mode 100755 install-sh create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/apple2.6 create mode 100644 src/apple2.h create mode 100644 src/compact.c create mode 100644 src/cpu-supp.c create mode 100644 src/cpu.S create mode 100644 src/cpu.h create mode 100644 src/debug.h create mode 100644 src/debug.l-cpp create mode 100644 src/debugger.c create mode 100644 src/disk.c create mode 100644 src/disk.h create mode 100644 src/display.S create mode 100644 src/font.txt create mode 100644 src/genfont.c create mode 100755 src/genglue create mode 100644 src/glue.h create mode 100644 src/gluepro.h create mode 100644 src/interface.c create mode 100644 src/interface.h create mode 100644 src/joystick.c create mode 100644 src/keys.c create mode 100644 src/keys.h create mode 100644 src/memory.S create mode 100644 src/misc.c create mode 100644 src/misc.h create mode 100644 src/opcodes.c create mode 100644 src/prefs.c create mode 100644 src/prefs.h create mode 100644 src/svideo.c create mode 100644 src/video.h create mode 100644 src/vidsup.c create mode 100644 src/xvideo.c diff --git a/.apple2 b/.apple2 new file mode 100644 index 00000000..2105cb25 --- /dev/null +++ b/.apple2 @@ -0,0 +1,11 @@ +speed = 100 +mode = ][+ undocumented +disk path = /usr/local/games/apple2/disks +color = interpolated +sound = pc speaker +joystick = pc joystick +joystick range = 256 +origin_x = 128 +origin_y = 128 +sensitivity = 3% +system path = /usr/local/games/apple2/rom diff --git a/ASM b/ASM new file mode 100644 index 00000000..649b7a5d --- /dev/null +++ b/ASM @@ -0,0 +1,15 @@ +Begin3 +Title: Apple // emulator for Linux +Author: alexb@csd.uu.se (Alexander Jean-Claude Bottema) + sl14@cornell.edu (Stephen Lee) + asc@mhpcc.edu (Aaron Culliney) + michael@talamasca.ocis.net (Michael Deutschmann) +Version: 0.7.4 +Entered-date: 2000-03-24 +Description: Apple II+, //e emulator. Uses svgalib or X. +Keywords: emulator, linux +Uploader: michael@talamasca.ocis.net (Michael Deutschmann) +Primary-site: ftp.ocis.net /pub/users/ldeutsch/release/ + 257k apple2-emul-0.7.4.tar.gz +Platform: Linux i386 +End diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..17bc46ea --- /dev/null +++ b/AUTHORS @@ -0,0 +1,11 @@ +Alexander Jean-Claude Bottema made the original +version of the emulator in 1994. + +Stephen Lee and particularly Aaron Culliney + have done much work on the emulator since. + +Michael Deutschmann cleaned up the +build sequence to use standard GNU tools, and is the present coordinator. + +Tom Lear maintains the Debian package of +this program, and has contributed some fixes. diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..f4780689 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1237 @@ +Thu Mar 23, 2000 : Michael Deutschmann + + * configure.in: set revision to 0.7.4, final release + +Thu Mar 2, 2000 : Michael Deutschmann + + * src/svideo.c (c_initialize_colors): Minor comment fix + + * src/xvideo.c (getshm): Fix handling of shmat() failure. (It + returns -1, not 0) + + * src/xvideo.c (getshm): When probing for preexisting shared + memory, use size of 0. + +Fri Feb 18, 2000 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3q + + * src/memory.S (iie_altzp_main,iie_altzp_aux): Fix handling + of language-card-off case. + + * src/svideo.c (c_initialize_colors): Reset lores colors to match + dhires colors. + * src/xvideo.c (c_initialize_colors): Follow svideo change. + + * src/memory.S (iie_altzp_aux): Removed redundant ret instruction + + * src/memory.S (lc_c083): fix handling of SS_LCSEC and SS_LCWRT. + +Fri Feb 4, 2000 : Michael Deutschmann + + * src/svideo.c (c_initialize_colors): Correct arguments to + vga_setpallete to be in proper range. Swap light-gray and + dark-gray to match Apple documentation. + + * src/xvideo.c (c_initialize_colors): Synchronize colors with svideo.S + + * src/debugger.c: Make "opcodes" pointer-to-const. + * src/debug.h: reflect above. + +Thu Feb 3, 2000 : Michael Deutschmann + + * src/memory.S (iie_ramwrt_aux,iie_ramwrt_main): minor comment fix + + * src/memory.S (iie_ramwrt_aux): fix erroneus handling of + 80store/hires + + * src/cpu.S (Continue): move ZeroOp to after exception branch. + + * src/cpu.S (ReplaceState): correctly restore stack pointer in + ALTZP mode. + +Wed Feb 2, 2000 : Michael Deutschmann + + * src/memory.S (iie_c3rom_peripheral, iie_c3rom_internal, + iie_check_c3rom): Invert sense of SS_C3ROM, to match rest of code. + +Tue Feb 1, 2000 : Michael Deutschmann + + * Updated copyright headers on all source files. + + * src/debugger.c (disasm): Removed printf (was left in from + debugging the debugger.) + +Mon Jan 31, 2000 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3p + + * Makefile.am: no longer distribute README-alpha + + * src/xvideo.c (video_init): Gracefully exit if XCreateImage or + XShmCreateImage fails. + + * src/compact.c (pre_compact, compact): Handle mkstemp and/or + mmap failure. + + * src/cpu.h: documentation update. (comment said cpu65__signal still + used by other modules, not true anymore.) + +Mon Nov 1, 1999 : Michael Deutschmann + + * src/prefs.c (color_table): match `INTERP' to "interpolated", + not "color" + + * src/display.S (video__write_even0_mixed,video__write_odd0_mixed): + added missing branch. + +Fri Oct 29, 1999 : Tom Lear + + * configure.in: bump revision to 0.7.3o + + * Removed two extra memset calls from the joystick code + - src/joystick.c: c_calibrate_joystick + + * Added bounds checking on temp, system_path, & disk_path - this + blocks several buffer overflows + - src/debugger.c: bload + - src/disk.c: disk_install + - src/interface.c: c_interface_disk_select, + c_interface_select_diskette, c_interface_parameters + - src/misc.c: c_initialize_apple_ii_memory + - src/mics.h: declaration of temp + - src/prefs.c: declaration of {system,disk}_path, load_settings + - src/prefs.h: declaration of {system,disk}_path + + * Fixed problem with giving up group permissions + - src/xvideo.c: video_init + +Sat Oct 28, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3n + + * src/Makefile.am: Distribute prefs.h + +Mon Aug 23, 1999 : Michael Deutschmann + + * src/misc.h: correct declaration of glyph arrays to be constant + + * src/opcodes.c: Made all items constant + * src/debugger.h: update declarations + +Sun Aug 22, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3m + + * src/prefs.c: made `clean_string' static + + * src/prefs.c: made match tables constant + + * src/prefs.h: new file, contains all declarations for configurable + parameters. + * src/prefs.c: added in definitions of above + + * src/misc.h: eliminated sound_mode, color_mode, apple_mode, and + system_path, and definitions of their values, since they are + now in prefs.c/prefs.h. Also removed prototypes for + load_settings and save_settings. + * src/keys.h: eliminated joy_mode, joy_step, joy_center_x, + joy_center_y, joy_range, half_joy_range, js_center_x, + js_center_y, js_timelimit, js_max_x, js_max_y, js_min_x, + js_min_y & definitions of joy_mode + values for same reason. + * src/interface.h: eliminated disk_path. + + * src/joystick.c: eliminated definitions of js_center_x, + js_center_y, js_max_x, js_max_y, js_min_x, js_min_y, js_timelimit. + + * src/interface.c, src/keys.c, src/misc.c, src/vidsup.c, + src/disk.c, src/debugger.c, src/joystick.c, src/prefs.c: + include prefs.h. + + * src/debugger.c (c_do_debugging): don't reset sound hooks on exit. + + +Sat Aug 14, 1999 : Michael Deutschmann + + * src/interface.c (c_interface_keyboard_layout): applied + Culliney's patch to text. Button numbering is changed. + +Thu Aug 12, 1999 : Michael Deutschmann + + * src/misc.c (c_set_altchar): Bug-fix - lowercase inverse chars + were shown as normal. + +Wed Aug 11, 1999 : Michael Deutschmann + + * src/font.txt: reorganized. Now includes interface box-drawing chars. + * src/genfont.c: changes to font-file format - now allows + multiple arrays. + * src/misc.h: + Replace "char_rom" declaration with "lcase_glyphs", "ucase_glyphs", + "mousetext_glyphs" and "interface_glyphs", which are now in font.c + * src/misc.c (c_initialize_font,c_set_primary_char,c_set_altchar): + Use new font arrangement. + * src/interface.c (c_load_interface_font): use new font arrangement. + +Tue Aug 10, 1999 : Michael Deutschmann + + * src/vidsup.c (video_loadfont): add new argument "mode" + * src/video.h: revise prototype and documentation. + * src/misc.c: revise callers. + +Sun Aug 8, 1999 : Michael Deutschmann + + * src/gluepro.h, src/cpu.S, src/display.S: correct assembler + errors revealed by new version of binutils. + + * src/debug.h, src/debug.l-cpp, src/debugger.c: Define opcodes as + "*opcodes", not brain-damaged "*opcodes[256]". Also changed + references. + + * src/debugger.c (get_current_rambank): correct typo. + + * src/opcodes.c: completely new (incompatible) table format, with + redundant data removed. + * src/debug.h: changed declarations of opcodes.c items. + * src/debugger.c (disasm): use new opcodes table + * src/debug.l-cpp: use new opcodes table + + +Sat Aug 7, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3l + + * src/prefs.l-cpp: removed + * src/misc.h: removed declarations of prefs.l-cpp items. + * src/misc.h: removed c_system_defaults and c_save_settings - + equivalent functions are now in prefs.c + * src/prefs.c: new file. + * src/Makefile.am: reflect above + + * src/misc.h: replace prototype for c_save_settings with + prototypes for load_settings and save_settings. + * src/misc.c (main): call load_settings, not c_system_defaults. + * src/misc.c (main): don't use lowercase_string. + + * src/interface.c (c_interface_parameters): + call save_settings, not c_save_settings. + * src/interface.c (pad_string): added as a static function, replacing + reference to old prefs.l-cpp. + + * src/keys.h: include joystick.c declarations + * src/misc.c, src/interface.c: remove declarations now in keys.h + +Fri Jun 23, 1999 : Michael Deutschmann + + * src/xvideo.c (keysym_to_scancode): add support for Break key. + +Sat Jul 16, 1999 : Michael Deutschmann + + * src/keys.c (c_periodic_update) : fix keys so that "next_key" is + reset before menu actions are executed. + + * src/keys.c: rebind PrintScreen and Pause keys. + +Thu Jul 7, 1999 : Michael Deutschmann + + * src/memory.S: use base_stackzp rather than zp_offset. Remove + iie_read_ram_zpage_and_stack and iie_write_ram_zpage_and_stack. + * src/misc.c: use base_stackzp rather than zp_offset. add glue + functions to replace ones removed from memory.S + * src/misc.h: declare base_stackzp, remove zp_offset. + + * src/memory.S (lc functions,altzp): set base_[de]000_{rd|wrt}, add + iie_versions. Remove lc-area accessor functions and lc_offset + * src/misc.c: implement lc-area accessors with glue system. Initialize + lc base variables, not lc_offset. No longer use seperate + accessors for iie. Use seperate lc_c08x hooks for iie. + * src/misc.h: declare lc base variables, remove lc_offset. Also + change prototypes to reflect added/removed function. + + * src/gluepro.h: bug fixes for GLUE_BANK_MAYBEWRITE + + * src/misc.h: remove iie_read_slot6 prototype, which was removed + earlier. + + * src/disk.c (c_write_normal_6): remove references to wr_trk_6 + and wr_sec_6. (they weren't used) + + * src/disk.c (c_read_normal_6, c_write_normal_6): replace references + to old_value_6 with old_value, a stack variable. + + * src/disk.c: removed old_value_6, wr_trk_6, wr_sec_6 + +Wed Jul 7, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3k + + * src/misc.c: use glue system to generate read_ram_default, + write_ram_default. + * src/memory.S: remove manual definitions of these hooks. + + * src/memory.S: placed SN() around declaration of softswitches + + * src/memory.S: corrected C3ROM/CXROM softswitches. Also + converted Cx00 hooks to use bases rather than offsets. + * src/memory.S: removed iie_read_c3rom, iie_read_cxrom + * src/misc.c: replace with glue system + * src/misc.h: added base_c3rom,base_cxrom; removed offset_c3rom, + offset_cxrom + + * src/genglue: modified to include all '#if' directives, etc. + from files. This makes glue.S ugly, but it's needed to so that + GLUE_ lines will respect conditionals. + + * src/display.S: removed unused macro offset_RAMRD_RAMWRT + + * src/memory.S: use bases, not offsets, for normal, text0, and hires0 + memory. Remove iie_read_ram_default, iie_write_ram_default, + iie_read_ram_text0, iie_write_screen_hole_text0, iie_read_ram_hires0, + iie_write_screen_hole_hires0 + * src/misc.c: replace functions with glue, use bases not offsets + * src/display.S: use bases, not offsets. + * src/misc.h: remove offset declarations, add base declarations + +Tue Jul 6, 1999 : Michael Deutschmann + + * src/disk.h: replace many _6 definitions with a single structure, + "disk6". Also includes some former static definitions from disk.c + * src/disk.c, src/debugger.c, src/interface.c: follow through + + * src/display.S (video__write_odd1_mixed): bug fix - + check SS_TEXT|SS_MIXED, not SS_TEXT|SS_HIRES. + + * src/memory.S (iie_80store_off): rewrote to properly set + SS_TEXTWRT/SS_TEXTRD/SS_HGRWRT/SS_HGRRD. Removed + offset_RAMRD_RAMWRT macro + +Mon Jul 5, 1999 : Michael Deutschmann + + * src/disk.c (disk_write_latch): bug fix -- disk_byte_6 not set. + + * configure.in: bump revision to 0.7.3j + + * src/memory.S: bug fix - typo in read_switch_secondary_page + + * src/display.S: remove "updating_screen" variable -- instead + temporarily clear some softswitches, restoring them from stack at + end. + + * src/display.S: remove "iie_mixed_lores0" and "iie_mixed_lores1" + -- they were identical to "iie_write_lores?" + + * src/display.S (iie_write_lores0, iie_write_lores1): properly + check if in auxillary bank + + * src/disk.c (disk_install): new function, handles insertion of + disk-related ROM and softswitches. + * src/misc.c (c_initialize_apple_ii_memory): don't load slot6.rom + - leave it to disk.c + * src/misc.c (c_initialize_tables): call disk_install instead of + inserting softswitches manually. + +Sun Jul 4, 1999 : Michael Deutschmann + + * src/configure.in: bump revision to 0.7.3i + + * src/disk.c (disk_read_phase): bug fix - set phase_change when stepping tracks. + + * src/display.S: (video__write_2e_text0): bug fix - check SS_TEXT|SS_MIXED, not SS_TEXT|SS_HIRES. + +Sat Jul 3, 1999 : Michael Deutschmann + + * src/Makefile.am: add glue.h, gluepro.h to headers + + * src/configure.in: up default MAX_APPLE_DELAY to 1000 + + * src/Makefile.am: invoke genglue from $(srcdir)/, not ./ + * src/Makefile.am: add glue.S to CLEANFILES + * src/Makefile.am: remove glue.S from distribution + + * src/Makefile.am: distribute genglue + +Fri Jul 2, 1999 : Michael Deutschmann + + * src/memory.S: bug fix: language card BANK2 was reversed. + * src/memory.S: bug fix: CXROM check was reading C3ROM. + + * src/Makefile.am: added './' to genfont/genglue invocations. + + * src/memory.S: redraw screen on change of 80col switch if DHIRES is + active. (formerly only TEXT and MIXED were checked). + +Wed Jun 30, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3h + + * src/genglue, src/glue.h, src/gluepro.h : new files + * src/Makefile.am: generate and include "glue.S" + + * src/disk.c: removed c_read_byte, c_write_byte. Added (using + glue facility) implementations of diskio.S functions, except + disk_read_nop + * src/diskio.S: removed + * src/Makefile.am: remove diskio.S from all builds + + * src/misc.c: install ram_nop on C0E0/2/4/6 instead of + disk_read_nop, which was removed. + +Tue Jun 29, 1999 : Michael Deutschmann + + * src/misc.h: added new "softswitches" bitmask variable and + supporting defines, removed old softswitch variables. + * src/debugger.c, src/interface.c, src/misc.c, src/xvideo.c, + src/memory.S, src/memory.S: change to new system. + * src/memory.S: declare "softswitches" + * src/display.S: corrected problem where wrong offset was used in + //e hires page #2. + * src/memory.S: some corrections to language-card semantics + (set bank on first write to C081/3/9/B, not second. + set bank on writes to C082/C08A) + +Mon Jun 28, 1999 : Michael Deutschmann + + * src/apple2.h: move virtual memory hooks... + * src/misc.h: ...to here (also fixed read_character declaration) + + * src/apple2.h: move SCANSTEP,SCANWIDTH,SCANHEIGHT definitions + * src/video.h: ... to here + + * src/video.h: added conditionals so header may be included in assembly + + * src/apple2.h: move _Flag and register definitions... + * src/cpu.h: ... to here + + * src/cpu.h: added conditionals so header may be included in assembly + + * src/cpu.S, src/display.S, src/memory.S: include "cpu.h" + + * src/cpu-supp.c, src/debug.l-cpp, src/debugger.c, src/disk.c, + src/interface.c, src/keys.c, src/misc.c, src/svideo.c, src/vidsup.c + src/xvideo.c: do not include "apple2.h" + + * src/cpu.S, src/display.S, src/memory.S, src/diskio.S: don't + define __ASSEMBLY__ -- we now use __ASSEMBLER__ which is preset + by the compiler. + + * src/diskio.h: changed to "apple2.h" + + * src/cpu.S: fixed bug re: NVZ_Flag + + * src/vidsup.c, src/video.h, src/display.c: introduce variable + video__strictcolors, replacing `strict_color'. + + * src/interface.c (c_interface_parameters), src/prefs.l-cpp: + remove references to strict_color. + * src/misc.h: remove strict_color. + + * src/memory.S: removed iie_read_slot6 -- identical with slotx + * src/misc.c: revised `caller' + +Sun Jun 27, 1999 : Michael Deutschmann + + * configure.in: bump revision to 0.7.3g + + * src/apple2.h: remove FLAG() kludge - assembler code now must + place $ explicitly + * src/cpu.S, src/memory.S, src/display.S: change to reflect this + + * src/cpu.S: used complement operator instead of Flag_Not definitions + * src/apple2.h: added missing NVZ_Flag define. + + * src/cpu.S: used OR operator instead of NVZC_Flag, BX_Flag, etc. + * src/apple2.h: removed unneeded _Flag and _Flag_Not defines + + +Thu Jun 24, 1999 : Michael Deutschmann + + * src/xvideo.c, src/svideo.c (c_initialize_keyboard, video_init): + Do not attach video_shutdown to signal handlers (there are no + safety issues with X, and svgalib handles this itself.) + + * src/sapple.c (video_init): remove unneeded save of keyboard + modes/termios. Also removed static variables. + + * src/xvideo.c, src/svideo.c (video_shutdown): Remove exit() call + * src/interface.c: removed "shouldn't get here" comment as it is no + longer accurate + + * src/video.h: reorganized, added documentation. + + * src/misc.c: removed unused variable vmode_active + + * src/keys.c: added dummy argument to c_periodic_update, so it is + a correct signal handler + * src/keys.h: updated prototype. + +Wed Jun 23, 1999 : Michael Deutschmann + + * src/svideo.c (video_init): bug fix. video__fb1 should be + initialized to vga_mem_page_1, not 0. + + * src/keys.c (c_periodic_update): bug fix. Clear `next_key' + before pausing. + + * src/keys.c (c_mygetch, c_read_raw_key) : added new variable + `in_mygetch' -- used to keep keyboard in //e mode in interface + even if ][+ selected. + + * src/xvideo.c (keycode_to_keysym): Removed "doRaw" argument, simplified. + * src/xvideo.c (video_sync): update caller + + * src/xvideo.c (keycode_to_keysym): Return correct scancodes for + PgUp,Home & End. Added support for Alt keys. + + * src/keys.c: Reassigned keys. Joystick buttons are now Alt keys + and Ins, rather than Del, End, PgDN + + * src/keys.h: Made kEND, kPGDN seperate from JB0 and JB1. Removed + kDELETE. + +Tue Jun 22, 1999 : Michael Deutschmann + + * src/joystick.c: Replace calls to `c_video_refresh' with `video_sync' + + * src/svideo.c, src/xvideo.c (c_video_refresh): remove + + * src/svideo.c, src/xvideo.c (c_flash_cursor): make static + * src/svideo.c, src/xvideo.c (video_sync): add call to c_flash_cursor + * src/keys.c (c_periodic_update): remove calls to c_flash_cursor, + and flash_cnt variable + * src/xvideo.c (c_flash_cursor): Move function above video_sync + in file (avoid forward reference) + + * src/video.h: remove prototypes for c_flash_cursor and + c_video_refresh + + * src/svideo.c, src/xvideo.c (c_initialize_video): rename to `video_init' + * src/misc.c: update caller + * src/video.h: update prototype, move to new interface section + + * src/debug.l-cpp: add #include of "keys.h" + + * src/svideo.c, src/xvideo.c (c_shutdown_video): rename to + `video_init' + * src/interface.c, src/debug.l-cpp: update caller + * src/video.h: update prototype, move to new interface section + +Mon Jun 21, 1999 : Michael Deutschmann + + * src/keys.c: rename static variable `menu_key' to `next_key' + + * src/keys.c (c_periodic_update,c_read_raw_key): Shift all + actions from c_read_raw_key to c_periodic_update. + c_read_raw_key now only manipulates `next_key' and `key_pressed' + + * src/keys.c (c_mygetch): new implementation, doesn't require + keyboard_off() + * src/svideo.c (c_mygetch, c_keyboard_off, c_keyboard_on, _mygetch): + remove + * src/svideo.c (c_initialize_keyboard) incorpate code from + removed c_keyboard_on + * src/xvideo.c (c_mygetch, c_keyboard_off, c_keyboard_on, + c_initalize_keyboard): remove, and remove calls to them + + * src/svideo.c (video_sync): Don't use keyboard_waitforupdate -- + it crashes -- use kludge instead. + + * src/keys.h: Changed kLEFT,kRIGHT,kUP,kDOWN,kESC to be + compatible with new mygetch. + + * src/keys.h: corrected prototype for c_periodic_update + + * src/keys.h: removed prototype for dead c_set_rubout_key + + * src/keys.h: added prototype for c_mygetch + + * src/video.h: removed prototypes for c_mygetch, c_keyboard_on, + c_keyboard_off + +Sun Jun 20, 1999 : Michael Deutschmann + + * src/misc.c: add constants timer_on and timer_off + * src/misc.h: add declarations. + + * src/svideo.c: add function video_sync() + * src/svideo.c: remove function c_poll_keyboard_input() + * src/svideo.c (c_initialize_keyboard,c_keyboard_on, c_keyboard_off): + remove all references to timer signal handler.) + + * src/misc.c (c_initialize_firsttime): set up timer signal hander + + * src/keys.c (c_periodic_update): add call to video_sync + + * src/keys.c (enter_debugger): add calls to disable/reenable timer + signal + + * src/video.h: added prototype for video_sync + + * src/xvideo.c (c_initialize_keyboard,c_keyboard_on, + c_keyboard_off, c_poll_keyboard_input): + remove all references to timer signal handler.) + + * src/xvideo.c (c_poll_keyboard_input): Rename to video_sync. + Remove call to c_periodic_update. + + +Sat Jun 19, 1999 : Michael Deutschmann + + * src/Makefile.am: no longer create seperate interface-80 module. + +Fri Jun 18, 1999 : Michael Deutschmann + + * src/vidsup.c (video_wider_int_font, video_int_font, + video_loadfont_int ): added + * src/vidsup.c (c_interface_print_char40_line): copied from interface.c + * src/vidsup.c (video_plotchar): added (adapted + from c_interface_print_char40) + + * src/video.h: added prototypes for video_plotchar and + video_loadfont_int + + * src/interface.c (c_load_interface_font): completely redone + * src/interface.c (c_load_character,c_interface_textcolor): removed + * src/interface.c (c_interface_print_char40_line, + c_interface_print_char40, c_interface_print_char): removed + (some code now in vidsup.c) + * src/interface.c (c_interface_print, c_interface_print40): + changed to one function `c_interface_print', added + colorscheme argument, and changed to use `video_plotchar' + * src/interface.c, src/debug.c, src/joystick.c: Changed callers to + c_interface_print, c_interface_print_char, and + c_interface_textcolor to new interface. + * src/interface.h: remove/modify prototypes for changed functions + + * src/interface.c: removed intermediate_font/interface_font decls. + +Tue Jun 15, 1999 : Michael Deutschmann + + * Changelog: bump revision to 0.3.7f + + * src/debugger.c, src/interface.c, src/memory.S, src/misc.c, + src/svideo.c, src/video.h, src/xvideo.c: Renamed c_setscreen to + video_setpage. + * src/video.h: moved video_setpage prototype to "new interface" + section of file (purely aesthetic). + + * src/video.h: removed spurious prototypes of write_ram_default, + write_unmapped_softswitch + +Sat Jun 12, 1999 : Michael Deutschmann + + * src/keys.c (c_periodic_update) : removed kluge surronding debugger + entry, creating new function `enter_debugger' + * src/keys.h: added prototype for `enter_debugger' + * src/cpu.S (ex_enter): call `enter_debugger', not `c_periodic_update' + * src/cpu.S (ex_enter): clear cpu65_signal when entering + + * src/cpu.S (do_step): rename to cpu65_step + * src/debugger.c, src/debug.l-cpp: revise callers + * src/cpu.h: add prototype for cpu65_step + + * src/cpu.S (cpu65_step, ex_enter): Handle setting DebugStepSig + internally + * src/debugger.c, src/debug.l-cpp: Remove all DebugStepSig references + + * src/cpu.S (ReplaceState): explicitly clear all registers + (preventing junk in high parts from tripping us up.) + + * src/apple2.h: removed prototypes for removed/renamed functions + do_step, do_write_memory, and do_write_lc. + + * src/display.S: Made "updating_screen" variable internal, and + managed it within video_redraw. + * src/interface.c (c_exit_interface): Removed references to + updating_screen + * src/interface.c (updating_screen): Removed declaration of + updating_screen. + + * src/interface.c (c_exit_interface): Removed second call to + video_redraw for nonvisual page - it was unnecessary. + +Fri Jun 11, 1999 : Michael Deutschmann + + * src/apple2.h: removed `prototype' for read_screen_hole + functions, which were removed earlier. + + * src/apple2.h: moved `prototypes' for write hooks in + `display.S', and update_video_screen... + * src/video.h: ... to here. + + * src/display.S, src/vidsup.c, src/svideo.c, src/xvideo.c, + src/video.h: mass rename of many functions + * src/memory.S, src/misc.c, src/interface.c: + update callers of update_video_screen, now video_redraw. + * src/interface.c (c_interface_print_char40): + update GM1 reference to video__fb1. + + * src/display.S: fixed up UpdateRows/UpdateHiresRows/iie_soft_write_* + system, which was disrupted in rename. + + +Thu Jun 10, 1999 : Michael Deutschmann + + * configure.in: Bump revision to 0.7.3e + + * src/misc.h: removed declarations that were moved to video.h + + * src/misc.h: Made "char_rom" extern + + * src/video.h, src/vidsup.c: removed crnt_active_svga_page, oldpage, + oldscreen (weren't used) + + * src/vidsup.c: moved even_colors, odd_colors from svideo.c/xvideo.c + * src/video.h: added extern declarations for above + + * src/debugger.c: copied declarations for global data from debug.c + to here. + * src/debug.h: changed declarations to extern. + + * src/vidsup.c: changed expanded_font and intermediate_font to + video__font and video__wider_font. + Also removed use of #define to rename intermediate_font in + 40-col mode. + * src/display.S: + Changed use of "expanded_font" and "intermediate_font" to two + defines, Font and Font80, which are connected as appropriate to + new variables + * src/video.h: added declaration of video__font and video__wider_font + + * src/vidsup.c (c_initialize_tables_video): made static. + + + * src/vidsup.c: routines expanded_col_* and expanded_col8_* renamed + to video__hires_* and video_wider_hires_*. The loop to generate + wider_hires was also revised. + * src/display.S: carry through change. #defines were removed + * src/video.h: carry through change. + + * src/display.S: replace references to text_row_offset with + hires_row_offset (which is just an extension of the latter + * src/vidsup.c (text_row_offset): remove + * src/vidsup.c (c_initialize_row_col_tables): remove + initialization of text_row_offset + * src/video.h (text_row_offset): remove declaration + + * src/vidsup.c (dhires_aux_page_offset): remove, as it is unused + * src/vidsup.c (c_initialize_row_col_tables): remove initialization + of dhires_aux_page_offset + * src/video.h (dhires_aux_page_offset): remove declaration + +Wed Jun 9, 1999 : Michael Deutschmann + + * configure.in: Bump revision to 0.7.3d + + * src/vidsup.c: new file + * src/video.h: added prototype for video_loadfont + * src/Makefile.am: added vidsup.c for apple2 (not complete for xapple) + + * src/misc.c (c_set_primary_char): now conditionalized for APPLE_IIE + * src/misc.c (c_initialize_font): no longer nulls 0xff char in + ][+ mode + * src/misc.c (c_set_primary_char,c_set_altchar,c_initialize_font): + rewritten to use video_loadfont. + * src/misc.c: intermediate_font decl/define removed. + + * src/vidsup.c (video_line_offset,dhires_colors1,dhires_colors2): + moved from misc.c + * src/vidsup.c (c_initialize_dhires_values, + c_initialize_hires_values, + c_initialize_row_col_tables): + moved from misc.c , prototypes corrected, made static + * src/vidsup.c (c_initialize_tables_video): + new function, based on c_initalize_tables from misc.c + * src/vidsup.c (video_set): + new function, based on c_initalize_vm from misc.c + * src/misc.c: removed things to appear in vidsup.c + * src/misc.c (c_initalize_table): + removed video-memory references, replaced with call to + video_set() + * src/misc.c: (c_initalize_vm): + removed calls to video-related stuff + + * src/misc.h: + removed decl of c_initialize_hires_values + removed decl of expanded_font + + * src/interface.c (c_initialize_parameters): + replaced call to c_initialize_hires_values with video_set. + + * src/vidsup.c (text_row_offset, + text_page_cols,hires_row_offset,hires_col_offset, + dhires_aux_page_offset) : copied from misc.h + * src/vidsup.c (expanded_col*, dhires_colors?, crnt_*_svga_page, + oldpage, oldscreen): copied from video.h + + * src/video.h (text_row_offset, + text_page_cols,hires_row_offset,hires_col_offset, + dhires_aux_page_offset) : moved from misc.h + + + * src/video.h: converted all declarations to extern + + * src/video.h: added prototype for video_set. + + * src/display.S: (iie_read_screen_hole_*): removed (identical to + iie_read_ram_*) + * src/misc.S (c_initialize_table): changed to reflect above + + * src/display.S: (iie_read_*, iie_write_screen_hole_*): moved to + memory.S + + * src/vidsup.c (c_initialize_table_video): set of read + functions removed. + + * src/memory.S, src/display.S: Corrected title in banner + * src/Makefile.am: Removed misc-80.o, added vidsup.o to xapple2 builds + +Sun Jun 7, 1999 : Michael Deutschmann + + * src/cpu.S, src/debugger.c : Removed debug_* variables, everything + is done to cpu65_current and cpu65_debug. + * src/cpu.h: revised/renamed cpu65_current and cpu65_debug + + * src/cpu.S, src/debugger.c : elided do_write_lc routine + + * src/apple2.h, src/*.S: renamed SYMBOL_NAME and ENTRY to SN and E + + * src/cpu.S, src/debugger.c : Watchpoint system changed. + + * src/cpu.S, src/cpu.h: new function cpu65_direct_write + * src/debugger.c: use it instead of do_memory_write + * src/cpu.S: removed do_memory_write + + * src/debug.h, src/debugger.c, src/misc.c: removed watch_* and + debug_scratch + + * src/Makefile.am: added "cpu.h" to noinst_HEADERS + + * src/misc.c (reinitialize): New function + * src/misc.c (c_initialize): Call reinitialize rather than repeat it + * src/misc.c (main): stuff moved out of loop into above functions. + +Sat Jun 6, 1999 + + * Changed interface to CPU subsystem: + * src/cpu-supp.c, src/cpu.h: added files + * src/compact.c, src/cpu.S, src/debug.l-cpp, src/debugger.c, + src/interface.c, src/keys.c: change to new interface. + + * src/apple2.h, src/cpu.h: Removed declarations for things now in cpu.h + (under different names) + + * src/misc.c (main): initialized watch_addrs to -2, not -1. + + * configure.in: Bump revision to 0.3.7c + +Fri Feb 26, 1999 : Michael Deutschmann + + * acinclude.m4: created, with macro A2_ASM_UNDERSCORES + * configure.in: Use this macro. + + * src/apple2.h: added definitions to replace + * src/cpu.S, src/memory.S, src/display.S, src/diskio.S: + Remove + + * src/svideo.c: Replace with + + * src/cpu.S (cpu65x02): Removed cruft, added proper save of registers + * src/cpu.S (ex_reboot): Restore registers before returning to program + * src/cpu.S (ex_reset): Instated label (no code change) to + non-debugger handler so cpu65x02 may branch to it. + * src/misc.c (main): Removed "exception_flag = ResetSig" lines, made + unnecessary by above. + +Wed Feb 24, 1999 : Michael Deutschmann + + * src/compact.c: New file, manipulates VM on memory table + * src/misc.h: specified aggressive alignment on table_memory + * src/misc.c: Inserted hooks to compact.c + + * src/configure.in: Inserted AC_FUNC_MMAP + * src/compact.c: Supply dummy functions if mmap() not available. + +Thu Feb 11, 1999 : Michael Deutschmann + + * src/misc.h: Changed memory table so that read and write tables + are interleaved. + * src/misc.c, src/cpu.S, src/debugger.S: Revise to use new tables + + * src/cpu.S: Fixed exception handler. (jz ex_reboot, not reboot) + +Mon Feb 8, 1999 : Michael Deutschmann + + * src/cpu.S: Optimized addressing-mode macros + +Sat Feb 6, 1999 : Michael Deutschmann + + * Begun version 0.7.3b + + * src/cpu.S: Removed exception-handling stuff from "Continue" + macro, placed it in a subroutine (exception) + + * src/cpu.S: Optimized GetFromPC_B and GetFromPC_W + * src/cpu.S: compensated in exception handler for fact that + GetFromPC_B no longer zeros %ah. + + * src/cpu.S: Optimized GetFromEA_W and GetFromMem_W + + * src/cpu.S: Made ADC and SBC use single decimal versions instead + of one for each addressing mode. + +Thu Feb 4, 1999 : Michael Deutschmann + + * src/cpu.S: Corrected BRK, RTI, PLP, PHP + + * src/cpu.S: Removed "65c02" versions of BRK, RTI, CLI. + + * src/memory.S, src/display.S: New files, split from (and + replacing) apple2.S + * src/Makefile.am: Reflect above change. + + +Tue Feb 2, 1999 : Michael Deutschmann + + * src/cpu.S: optimized ASL, ROL, ROR, LAN, LOR, SBC, DCP, AXM, ISB + + * src/cpu.S: Globally replaced many uses of bt with + testb, which is shorter and faster. + +Mon Feb 1, 1999 : Michael Deutschmann + + * src/apple2.h: Comment update + + * src/cpu.S: Corrected TSB, TRB + * src/cpu.S: Removed FlagNV + + * src/cpu.S: Optimized FlagNVZC + (486 cycle count is the same, but code is more compact) + + * src/cpu.S: Optimized BIT + +Sun Jan 31, 1999 : Michael Deutschmann + + * Makefile.am: Distribute `README-alpha' + + * src/cpu.S: Optimized ROL, ROR, ANA and LAN instructions + + * src/cpu.S: Removed read_memory,read_memory_word,write_memory. + Added more macros for accessing memory, changed code + to use them. + In a few places, debugger hooks are no longer set, + but they weren't necessary (I think) + +Wed Jan 27, 1999 : Michael Deutschmann + + * Begun Version 0.7.3a + + * src/video.h: removed c_setpage and vmode_active + , replaced GM with GM1 and GM2 + * src/svideo.c: removed c_setpage + * src/svideo.c (c_setscreen): rewritten + * src/xvideo.c: removed c_setpage + * src/xvideo.c (c_setscreen): rewritten + * src/xvideo.c (c_initialize_video): added code to preset buffer + pointers + * src/apple2.S: removed setpage, and references to c_setpage and + vmode_active + * src/apple2.S: (PlotTextPagePre,CalcHiresGM,PlotDHires,PlotByte, + Plot80Character) + inserted extra GM arg to select GM1 or GM2. + updated callers + * src/debugger.c,src/interface.c,src/misc.c: + removed references to c_setpage + * src/interface.c: changed GM to GM1 + * src/misc.c: removed references to vmode_active. + + * src/video.h, src/svideo.c, src/xvideo.c: + Removed c_clear_video - now integrated into + c_initialize_video + * src/misc.c: + Removed reference to c_clear_video + +Sun Jan 24, 1999 : Michael Deutschmann + + * src/Makefile.am: Distribute "ASM" file. + +Fri Jan 22, 1999 : Michael Deutschmann + + * Begun Version 0.7.3 + + * src/Makefile.am: Added warning about genfont and cross compilation. + + * src/Makefile.am: Added dist-hook hack. + + * Makefile.am: Renamed `apple2.lsm' to `LSM' + + * src/Makefile.am: Removed -80.o files from BUILT_SOURCES - it + wasn't needed. + + * disks/Makefile.am: Added several more files to distribute + +Thu Jan 7, 1999 : Michael Deutschmann + + * src/*.[Sch]: Replaced copyright banners on all files. + +Wed Jan 6, 1999 : Michael Deutschmann + + * src/Makefile.am: add debug.c, prefs.c to CLEANFILES + (they depend on configuration) + + * src/opcodes.c: new file, derived from 6502.h,65c02.h,undocumented.h + * src/debug.h: added definitions for opcodes.c + * src/debugger.c: use opcodes.c rather than including headers + * src/Makefile.am: add opcodes.c to extra-source-file lists + * src/ChangeLog: add opcodes.o to @DEBUGGER_O@ when debugging + is enabled. + + * src/Makefile.am: fixed xapple_80col_DEPENDENCIES + + * src/cpu.S: new file, derived from + 6502.h,65c02.h,undocumented.h,defs.h,apple2.S + * src/apple2.h, src/misc.c: Changed method of reassigning opcode table + * src/apple2.S: removed code now duplicated in cpu.S + * src/apple2.S: inserted most of defs.h + * src/6502.h,src/65c02.h,src/undocumented.h,src/defs.h: removed + + * src/cpu.S (cpu65x02): removed call to set_page + * src/misc.c: moved some initialization commands to compensate. + + * src/configure.in,src/Makefile.am: added code so that svgalib + version can be compiled without X, and vice versa. + + * src/interface.c(c_interface_parameters): don't mess with the + emulator font. + + +1999-01-06 : + + * Merged old CHANGES stuff into this file. Reformatted the + comments, but the content remains the same. + + (Michael: Revision 0.7.2 begins here) + +Mon Dec 21, 1998 : Michael Deutschmann + + * src/Makefile.am: distribute `debug.l-cpp', `prefs.l-cpp' files + + * src/Makefile.am: specified `font.c' to be removed by make clean + +Sun Dec 20, 1998 : Michael Deutschmann + + * src/misc.c: + (c_set_altchar,c_set_primary_char): added call to + update_video_screen(). + (c_initialize_charset): Replaced call to c_set_primary_char with + copy of most of its code (since update_video_screen is unsafe + to call here) + + (c_initialize_charset): fixed conditional so that 0xff char is + still removed if APPLE_IIE not defined. + + (c_initialize_charset): Removed "if (!altchar_flag)" - it is + always true here. + + * src/keys.c: + (c_set_rubout_key) Removed. + +Fri Dec 18, 1998 : Michael Deutschmann + + * Started revision 0.7.1 + + * configure.in: set version + + * Makefile.am: distribute '.apple2' + + * src/Makefile.am: Changed filename of SVGA apple2 back to just + `apple2' (from `sapple'). + + * src/Makefile.am: Fixed bug - seperate apple2-80.o was not being + made. + + * src/apple2.h: comments added regarding flag bits. + + + +Changes in 0.06 (Aug 98) : Aaron Culliney + + * Separated SVGAlib specific stuff into svideo.c. Added X + Windows frontend support in xvideo.c. The X frontend works + by doing an X(Shm)PutImage() of the emulator's framebuffer + around 30 times a second. This saves us from changing the + internal video routines (they assume direct access to an + 8bit framebuffer), and it's a heck of a lot faster than + trying to do an XPutPixels() on each change. The X frontend + only currently works for 8bit displays. Make sure you run + it using a mode (specified in XF86Config) that has a bit + depth of 8 (not 16 or greater). + + * We now build three versions of the emulator: svideo_320x200, + xvideo_320x200, xvideo_640x400. The last one really isn't + 640x400 for optimization reasons (568x384) although it + probably should be... Sorry, but there's no support for + switching resolutions on the fly, we ifdef it in with a new + define "_640x400". + + * Provided 80column support for the 640x400 X version. Now + you can PR#3 (running as //e) and get 80 columns. This + change required a resolution of at least 560 horizontal + pixels (Apple //e specs). + + * Both SVGA and X versions need to be suid root (for PC + speaker port access and SVGA stuff). But both versions now + give up root access during video initialization. This means + that disk access is now done as *you* (not root) even when + g(un)zipping images for loading. Before images would be + g(un)zipped as root. There was something about this that + made me uneasy... Now it's up to you to give the + appropriate user/group permissions to your disk image + repository. I make no claim about the security fitness of + this emulator. See the other READMEs and files for more + information/disclaimers. + + * Did a 180 on the disk image selection menu. now tries + to open disk images as read-only, 'W' for both read-write. + Of course this will only work if you have the correct file + permissions set (see above). I find this more convenient + b/c I play alot of the arcade games where you don't ever + save game state. + + * Removed the disk "Information" submenu. I never use it. Do + you? + +Changes in 0.05 (Feb 98) : Aaron Culliney + + * Added support for 65c02 instructions. The programs that + I've tested which use them work just fine. + + * Added support for 128k //e EXCEPT 80 column mode, B/W + DHIRES mode, and MouseText character set. The two + unimplemented video modes require major changes to current + video routines, thus a next version... New supported images + are copy ii+ 9.0, diagnostics //e, marble madness, airheart, + legend of blacksilver, pirates!... + + * Fixed some old problems with HIRES colors being off around + byte edges in interpolated/color modes. but we still give + you the option to use these "lazy" modes since emulation is + faster with them enabled... + + * You now have several new options in your .apple2 file. I + suggest either copying the distributed one over your + existing one, or merging the changes in. + + * Fixed some potential security bugs where a user could + traverse into sensitive directories by using the disk + selection interface. The current emulator version is not + guaranteed to be foolproof since it has to be installed suid + root for normal users to use it. Sysadmins should take + extra precautions as they see fit. + + * Added and deprecated some options in the debugger interface + to support the new 128k //e. see the DEBUGGER file for more + info. DEBUGGER support is not default compiled in. + + * Added some extra options to the .config file that you build + into the emulator. One big one: a way to set the max delay + count in the emulator to bring Apple ][ emulation rates down + to normal on high end pentiums!... 100 is the default delay + rate (which works just fine for low end 386-Pentium100's). + +Changes in 0.04 (June 97) : Aaron Culliney + + * Added PC Joystick Support. You must have the joystick + kernel loadable module 0.8.0 correctly configured and + installed to use this feature. + + * Changed the way the emulator handles the language card + memory space. We no longer patch rom/ram on lc_c08x + functions. I did this because under certain conditions the + previous versions of the emulator would run a lot slower. + Now you may notice the emulator running a tad slower in + general (because of the range checking), but Ultima 4 and + Arctic Fox (formerly unplayable) should now be just fine. + + * Changed the way the .apple2 preferences file is handled. I + Did this mainly to support saving of PC Joystick parameters, + and I'd rather let flex do the dirty work of regexp + matching. + + * Changed the disk interface and main interface menu. In the + disk interface, you can now see which disk is in the drive, + and with what permission for read/write drive 1. You + can eject this disk or force it to be write-protected. In + the main menu screen, you have more parameters to play + around with (associated with the pc joystick add-on). + + * Disk image files are now opened with user privileges, not + root privileges, even though the program is suid root. + gzip'ed disks are still handled as root, but we no longer + call the unsecure system() to do the dirty work. Instead we + fork and directly exec "/bin/gzip". + + * General bug fixes and enhancements. + +Changes in 0.03: (Jan-Feb 97) : Aaron Culliney + + * Fixed language card initialization bug. + + * Improved colors. Seems that Greens and purples we're + switched around. The colors are still slightly off, and + color interpolation seems screwy (TODO). + + * Added apple II debugger interface. This requires flex + version 2.5.2. (You can compile this into the program or + leave it out.) Type F7 to get into the debugger and type a + '?' to see a command summary. Check out the file DEBUGGER + for more info. + + * Added support for standard 232960 .nib disks. + + * Added a more intuitive interface to selecting disks. You + can now traverse forward and backward in a directory + hierarchy with the base directory set by your .apple2 config + file. + + * changed keymap: shift-p = @ and shift-N = ^, just like my + old II+ keyboard. + +Changes in 0.02: (8 Dec 1995) +----------------------------- + + * Ctrl-C will not kill the emulator with newer SVGAlib. Please + use SVGAlib > 1.2.9 for best results. + + * Rudimentory REPT key handling. It's too fast though. + + * The assembler files now compiles under ELF. + + * Not every SVGA card can do page-flipping. The emulator now + checks for this and fall back to VGA if it can't. + + * Keymap has changed a bit. Backspace and ']' is now <-, '[' is + REPT. + + * Disk extension changed to the more common .dsk (and a2d.info to + dsk.info). + + +Changes in 0.01: (9 Oct 1994) +----------------------------- + + * Standard VGA support with some performance degradation. + (When page flipping occurs, 64K memory banks are swapped; + hence the performance degradation.) + + * -vga flag switch added, e.g. "apple2 -vga"; forces standard + VGA detection. + + * (Trident) TVGA8900 page flipping bug fixed. + + * File names may now contain any character codes. (The previous + version had some problems with compressing/uncompressing file + names with extraordinary characters.) + + * Diskette selection retains last cursor position. diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..b42a17ac --- /dev/null +++ b/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/LSM b/LSM new file mode 100644 index 00000000..5c1ace8e --- /dev/null +++ b/LSM @@ -0,0 +1,16 @@ +Begin4 +Title: Apple2/Linux +Version: 0.7.4 +Entered-date: 2000-03-24 +Description: Apple II+, //e emulator. Uses svgalib or X +Keywords: apple2, emulator +Author: alexb@csd.uu.se (Alexander Jean-Claude Bottema) + sl14@cornell.edu (Stephen Lee) + asc@mhpcc.edu (Aaron Culliney) +Maintained-by: michael@talamasca.ocis.net (Michael Deutschmann) +Primary-site: ftp.ocis.net /pub/users/ldeutsch/release/ + 257k apple2-emul-0.7.4.tar.gz +Alternate-site: metalab.unc.edu /pub/Linux/system/emulators/ +Copying-policy: GPL +Platforms: x86 CPU, either svgalib or X-windows +End diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..9ed7558e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = disks src + +EXTRA_DIST = README.debugger TODO LSM ASM PROBLEMS .apple2 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..133c891e --- /dev/null +++ b/Makefile.in @@ -0,0 +1,320 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +DEBUGGER_O = @DEBUGGER_O@ +JOYSTICK_O = @JOYSTICK_O@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +PROGS = @PROGS@ +VERSION = @VERSION@ + +SUBDIRS = disks src + +EXTRA_DIST = README.debugger TODO LSM ASM PROBLEMS .apple2 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ +Makefile.in NEWS TODO acinclude.m4 aclocal.m4 configure configure.in \ +install-sh missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..868251cb --- /dev/null +++ b/NEWS @@ -0,0 +1,260 @@ +Changed in 0.7.4: + +Many bugs have been fixed, including a calling-convention mistake that +could cause unpredictable behavior on reboot. Potential buffer overflows +have also been corrected. + +Some key assignments have changed. Joystick buttons are now Left-Alt, +Right-Alt & Insert. Delete, formerly a joystick button, now produces the +DEL ascii code. Reboot is now Break (Ctrl-Pause), and Reset is now +Ctrl-Printscreen. (This is reversed from 0.7.3) + +Some significant optimizations were also made in the assembly code. The +large memory-access indirection table is now compressed using virtual +memory tricks, to slightly reduce cache load and swap requirements. + +Also many cleanups have been made in the internal code. This is +user-invisible, and far from complete. When done, it will become easier to +add new interface cards, video drivers, and other stuff, as well as port +to other unixes. + +Changed in 0.7.3: + +More makefile/configuration bugs were fixed. + +The `Mystery House' sample disk, which was accidently omitted from my +distributions, has been reinstated. Also, I've added a new sample +disk image - William Night's emulator performance tests. + +Changed in 0.7.2: + +The configure script will now react to absence of X Windows or SVGAlib by +only building an emulator for the remaining graphics system. + +A makefile bug that caused xapple-80col not to depend on +all it's source files was fixed. Also, the alternate character set is now +correctly restored on exit from the menu. + +Some major cleanups were done to the assembly-language files. This is +invisible to the user, but should make further enhancement a little saner. + +The banners on the source code have been synchronized. + +Changed in 0.7.1: + +1. Fixed a makefile bug that caused xapple-80col to be miscompiled. + +2. Put sample .apple2 (config file) back in. It was accidentally excluded +from 0.7. + +3. The SVGA emulator is again named `apple2', not `sapple2'. + +Changed in 0.7: (Sep 98) + +Version 0.7 - Michael Deutschmann + +1. Replaced "character.rom" and Aaron's MouseText table in misc.c with +a single file, font.txt, which is converted into a packed c table by a +generator utility. + +2. Overhauled Makefile system. We now use GNU autoconf/automake. + +Note: This hasn't been tested extensively. Also, there are a few automake +tricks I haven't bothered with - I added them to TODO. + +Changed is 0.06: (Aug 98) +------------------------- + +Version 0.06 - Aaron Culliney +My code changes have nothing to do with my employer, GTE +Internetworking, BBN Technologies. They were written completely on my +own time and on my own machine. + + 1) Separated SVGAlib specific stuff into svideo.c. Added X Windows + frontend support in xvideo.c. The X frontend works by doing an + X(Shm)PutImage() of the emulator's framebuffer around 30 times a + second. This saves us from changing the internal video routines (they + assume direct access to an 8bit framebuffer), and it's a heck of a lot + faster than trying to do an XPutPixels() on each change. The X + frontend only currently works for 8bit displays. Make sure you run it + using a mode (specified in XF86Config) that has a bit depth of 8 (not + 16 or greater). + + 2) We now build three versions of the emulator: svideo_320x200, + xvideo_320x200, xvideo_640x400. The last one really isn't 640x400 for + optimization reasons (568x384) although it probably should be... + Sorry, but there's no support for switching resolutions on the fly, we + ifdef it in with a new define "_640x400". + + 3) Provided 80column support for the 640x400 X version. Now you + can PR#3 (running as //e) and get 80 columns. This change required + a resolution of at least 560 horizontal pixels (Apple //e specs). + + 4) Both SVGA and X versions need to be suid root (for PC speaker port + access and SVGA stuff). But both versions now give up root access + during video initialization. This means that disk access is now done + as *you* (not root) even when g(un)zipping images for loading. + Before images would be g(un)zipped as root. There was something about + this that made me uneasy... Now it's up to you to give the + appropriate user/group permissions to your disk image repository. + I make no claim about the security fitness of this emulator. See the + other READMEs and files for more information/disclaimers. + + 5) Did a 180 on the disk image selection menu. now tries + to open disk images as read-only, 'W' for both read-write. + Of course this will only work if you have the correct + file permissions set (see 5 above). I find this more convenient b/c + I play alot of the arcade games where you don't ever save game state. + + 6) Removed the disk "Information" submenu. I never use it. Do you? + + + +Changes in 0.05: (Feb 98) +------------------------- + +Version 0.05 - Aaron Culliney +My code changes have nothing to do with my employer, GTE +Internetworking, BBN Technologies. They were written completely on my +own time and on my own machine. + + 1) Added support for 65c02 instructions. The programs that +I've tested which use them work just fine. + + 2) Added support for 128k //e EXCEPT 80 column mode, B/W +DHIRES mode, and MouseText character set. The two unimplemented video +modes require major changes to current video routines, thus a next +version... New supported images are copy ii+ 9.0, diagnostics //e, +marble madness, airheart, legend of blacksilver, pirates!... + + 3) Fixed some old problems with HIRES colors being off around +byte edges in interpolated/color modes. but we still give you the +option to use these "lazy" modes since emulation is faster with them +enabled... + + 4) You now have several new options in your .apple2 file. I +suggest either copying the distributed one over your existing one, or +merging the changes in. + + 5) Fixed some potential security bugs where a user could +traverse into sensitive directories by using the disk selection +interface. The current emulator version is not guaranteed to be +foolproof since it has to be installed suid root for normal users to +use it. Sysadmins should take extra precautions as they see fit. + + 6) Added and deprecated some options in the debugger interface +to support the new 128k //e. see the DEBUGGER file for more info. +DEBUGGER support is not default compiled in. + + 7) added some extra options to the .config file that you build +into the emulator. One big one: a way to set the max delay count in +the emulator to bring Apple ][ emulation rates down to normal on high +end pentiums!... 100 is the default delay rate (which works just fine +for low end 386-Pentium100's). + + + +Changes in 0.04: (June 97) +----------------------------- + +Version 0.04 - Aaron Culliney +My code changes have nothing to do with my employer, BBN. They were +written completely on my own time and on my own machine. + + 1) Added PC Joystick Support. You must have the joystick +kernel loadable module 0.8.0 correctly configured and installed to use +this feature. + + 2) Changed the way the emulator handles the language card +memory space. We no longer patch rom/ram on lc_c08x functions. I did +this because under certain conditions the previous versions of the +emulator would run a lot slower. Now you may notice the emulator +running a tad slower in general (because of the range checking), but +Ultima 4 and Arctic Fox (formerly unplayable) should now be just fine. + + 3) Changed the way the .apple2 preferences file is handled. I +Did this mainly to support saving of PC Joystick parameters, and I'd +rather let flex do the dirty work of regexp matching. + + 4) Changed the disk interface and main interface menu. In the +disk interface, you can now see which disk is in the drive, and with +what permission for read/write drive 1. You can eject this disk +or force it to be write-protected. In the main menu screen, you have +more parameters to play around with (associated with the pc joystick +add-on). + + 5) Disk image files are now opened with user privileges, not +root privileges, even though the program is suid root. gzip'ed disks +are still handled as root, but we no longer call the unsecure system() +to do the dirty work. Instead we fork and directly exec "/bin/gzip". + + 5) General bug fixes and enhancements. + + +Changes in 0.03: (Jan-Feb 97) +----------------------------- + +Version 0.03 - Aaron Culliney +My code changes have nothing to do with my employer, BBN. They were +written completely on my own time and on my own machine. + + 1) Fixed language card initialization bug. + + 2) Improved colors. Seems that Greens and purples we're +switched around. The colors are still slightly off, and color +interpolation seems screwy (TODO). + + 3) Added apple II debugger interface. This requires flex +version 2.5.2. (You can compile this into the program or leave it +out.) Type F7 to get into the debugger and type a '?' to see a +command summary. Check out the file DEBUGGER for more info. + + 4) Added support for standard 232960 .nib disks. + + 5) Added a more intuitive interface to selecting disks. You +can now traverse forward and backward in a directory hierarchy with +the base directory set by your .apple2 config file. + + 6) changed keymap: shift-p = @ and shift-N = ^, just like my +old II+ keyboard. + +Changes in 0.02: (8 Dec 1995) +----------------------------- + + * Ctrl-C will not kill the emulator with newer SVGAlib. Please + use SVGAlib > 1.2.9 for best results. + + * Rudimentory REPT key handling. It's too fast though. + + * The assembler files now compiles under ELF. + + * Not every SVGA card can do page-flipping. The emulator now + checks for this and fall back to VGA if it can't. + + * Keymap has changed a bit. Backspace and ']' is now <-, '[' is + REPT. + + * Disk extension changed to the more common .dsk (and a2d.info to + dsk.info). + + +Changes in 0.01: (9 Oct 1994) +----------------------------- + + * Standard VGA support with some performance degradation. + (When page flipping occurs, 64K memory banks are swapped; + hence the performance degradation.) + + * -vga flag switch added, e.g. "apple2 -vga"; forces standard + VGA detection. + + * (Trident) TVGA8900 page flipping bug fixed. + + * File names may now contain any character codes. (The previous + version had some problems with compressing/uncompressing file + names with extraordinary characters.) + + * Diskette selection retains last cursor position. diff --git a/PROBLEMS b/PROBLEMS new file mode 100644 index 00000000..e1896489 --- /dev/null +++ b/PROBLEMS @@ -0,0 +1,115 @@ +Known issues with the emulator: + +Emulation Fidelity: + +- Disk emulation. The emulator is not very realistic. It handles almost +all non-copyprotected disk access okay, but copyprotected or diagnostic +programs may be confused by our drive, which magically spins at precisely +the optimal speed. (see Specific Programs, below). + +- Medium Resolution graphics. This is a rarely used //e mode that is to +Low-Res what 80 Column text is to 40 column text. We don't support it as +yet, although it should be relatively simple. + +- Joystick. The apple joystick hardware is read by measuring the time it +takes for a specific softswitch to clear. The emulator cannot as yet +compensate for the speed of the loop used to measure the joystick -- +applications using ROM routines will be fine, but custom joystick code +may become mistuned. The Range configuration feature can be used to +compensate for this. + +- We don't emulate the //e's vertical blanking interval detection feature. + +Graphics: + +- Composite graphics artifacts are not emulated. This is not a big +interest to me (Michael), but the previous programmers have suggested it. + +- B/W color setting does not apply to lores or double hires. This +generally is not an issue in practice though, as it's really only needed +to avoid color fringing in b/w hires images. + +- Double Hires mode is always 140x192 color. Some applications use it as +a 560x192 b/w display however. Note that most applications indicate +which mode they want using the high bit of the dhires data bytes, so it +wouldn't need to be a preferences setting. + +- If an 80-column mode is selected in the low-res emulator, nothing will +be written to the display -- the image from the last video mode will +remain on the screen. If a menu is brought up it will `stick'. This may +make people think the emulator crashed, although it will recover if the +application returns to 40-column mode. + +- There is no 80-column mode for svgalib apple2. It would be possible on +standard VGA, although there are not enough colors to do flashing letters +by palette tricks as we do now. + +- In X, the emulator window takes over the palette, causing all the other +windows to be miscolored. We only need 20 or so colors, so it would be +better if we could share the common palette. + +Keyboard: + +- Key Handling is a little messy, especially with the way the X support +is bolted on top of core code originally designed for SVGA scancodes. + +- Presently, the Backspace key is interpreted as Left-Arrow (Code 0x88). +It could be argued that it should be interpreted as Delete (Code 0xff) +instead. Real Apples had no seperate Backspace key, but the //e's Delete +key was in an analogous position to the PC's Backspace). The PC +keyboard's Delete is assigned to 0xff (in //e mode). + +- If you're using Apple ][+ mode, the keyboard may appear broken. That's +a feature -- the program is imitating the historical ][+ keyboard layout. +Press F5 to see a map. Maybe we should add a means to turn it off. + +- On my X system, without explict xmodmap or xkbcomp intervention, +Break (reset) won't work with XKB enabled, and PrintScreen (reboot) won't +work with it disabled. + + This is X's fault, and I've sent them a bug-report, but maybe we should +consider moving the keys (again...) + +Miscellany: + +- Older versions of this file note problems with scandir() in the +presence of orphan symlinks in some versions of the C library. Hasn't +been a problem for my glibc 2.1.2 system. + +- Presently the programs are not automatically set SUID on install. + +- The emulator requires ROMs for both ][+ and //e even if only used to +emulate one of them. + +- In theory, typing "Ctrl-Left Alt-Pause" should be equivalent to +"Ctrl-Open Apple-Reset" and make the //e reboot. This doesn't work +properly in practice. Somehow CXROMINT is not cleared at disk-interface +detection time, so the disk won't boot. + + (Ctrl-Right Alt-Pause activates diagnostic mode, as expected.) + +Specific Programs: + +- Some programs (Computist's Nibbler, Sword of Kadash Master copy for +example) lock up. It appears (in debugger) that they are reading the disk +with the motor off. Perhaps they pulsed the real Apple's drive motor to make +it turn slower? + +- ProDOS will refuse to format disks, claiming that the disk is too slow. + +- ``Alternate Reality: The City'' seems to get jammed, rapidly changing +the video mode. I'm not sure if this is a real failure, or just a special +effect that takes longer than I'm willing to wait to finish (mode switches +would be much faster on a real Apple.) I can get into the program +with some nontrivial debugger manipulation to `short out' the offending loops. + +- ``Moon Patrol'' will crash in ][+ mode at the end of the first level +(ie: Point E). This is caused by a "02" opcode at address 1E15, an +undocumented HANG instruction. //e mode works, since the 65C02 treats +this instruction as a no-op. + + Moon Patrol may actually be //e-only. Yet this seems a gratutious +incompatibility, since the fact you can play the first level (and further +ones using the debugger) under ][+ mode indicates it doesn't need any //e +features. Perhaps the bug was introduced by the people who cracked it's +copy protection. diff --git a/README b/README new file mode 100644 index 00000000..0aafdb4f --- /dev/null +++ b/README @@ -0,0 +1,408 @@ +************************************************************************** +* Apple II+ Emulator version 0.7 for Linux * +* * +* Original Author: Alexander Jean-Claude Bottema * +* Email : d91a1bo@meryl.csd.uu.se * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the Free Software * +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * +* * +* Modified: Dec 8 1995 by Stephen Lee * +* Modified: Jan 97 by Aaron Culliney * +* * +* Modified: Jun 97 by Aaron Culliney * +* * +* Modified: Feb 98 by Aaron Culliney * +* * +* Modified: Aug 98 by Aaron Culliney * +* * +* * +* Modified: Sep 98, Dec 98, Jan 98, Jun 99 * +* by Michael Deutschmann * +* * +* * +************************************************************************** + +NOTE: + This is basically the original README. See the CHANGES file +first for information on this specific version of the emulator. Then +read section 0 (installation) in this file for cookbook compilation / +installation instructions. Other information in this file may be +outdated, so read the manpage for up-to-date runtime instructions. + +Contents +======== + +0. Installation issues (briefly) +1. Why did I make an Apple II+ Emulator when there are so many available? +2. System Files +3. Keyboard & keys +4. Diskette database +5. Future plans +6. Status of the current emulator +7. Can you port this to DOS? +8. Availability +9. Known problems +10. Changes since the last +11. Final words + + +0. Installation issues (briefly) +================================ + +Requirements: SVGA lib version 1.2.9 (or later, see 9.) Tested under 1.2.13. + Kernel 2.0.X. Tested under 2.0.36pre12. + libc 4.4.4 (or later). Tested under glibc-2.0.6 + joystick 0.8.0 kernel module for PC Joystick support. + flex 2.5.2 (for compiling lex files) + + +1) Unpack this distribution in a temporary directory. + +2) Run "configure" for a normal build, or "configure --enable-debugger" +to add debugger support. (Other GNU autoconf options, such as --prefix, +may of course be used.) You may provide optimizations in the enviroment +variable CFLAGS. + +3) Type "make" to make the program. As root, type "make install" to +install the programs in $(BINDIR) and the man page in $(MANDIR), (both +configurable at the configure line). The sysadmin should enable the +setuser bit on "apple2" in order for it to use the VGA. Enabling setuser +on "xapple2" will allow use of the PC speaker, but is not essential. + +4) Copy the .apple2 configuration file to your home directory, and +read the manpage that was installed for further information on how to +configure this file. You can configure most of the settings from +within the emulator, (F10 for the menu screen), but you need the +system path correctly set to point to the rom files before you start +the emulator. The emulator won't run without the correct rom files +(see the manpage). + +5) After you're done configuring, type "xapple2" to run the +emulator under X or "apple2" to run using svgalib. There are two X11 +versions for different resolutions. Once running, F1 selects disk +drive #1, F2 selects disk drive #2, F10 gives you the main menu of +runtime parameters, and F5 shows you the keyboard lay out. + + +1. Why did I make an Apple II+ Emulator when there are so many available? +========================================================================= + +For three reasons. The first is that there are no Apple II emulators +especially written for Linux; hence they do not take advantages that +are commonly provided in Linux systems, e.g. the SVGA library +distribution. However, there is an Apple II emulator for X-Windows +that easily can be compiled on most UN*X architectures, but the major +disadvantage is slow emulation. You cannot obtain a fast emulator by +writing it in C, despite the elegant optimizations provided by GNU-C, +but of course it becomes more portable if you do that. + +By contrast, this Apple II emulator is partly written in 386 (AT&T) +assembler; partly in C. Only those issues that were not time critical +were written in C. Especially the CPU emulation was written in +optimized assembler to achieve optimum performance. The emulator +approximately runs twice as fast as an ordinary Apple II+ computer if +it is running on a 486 DX-50. + +The second reason is that there is no Apple II emulator which is 100% +usable. Either it is too slow or it is simply too fast (= there is no +option to trim the speed of the emulator). Furthermore, many +implementors happily avoid implementing mixed text/graphics in high +resolution mode; mostly because it complicates the programming. I have +never seen an Apple II+ emulator that is entirely complete. I think +most emulators fail on implementing the undocumented 6502 instructions +(those that are listed as ???), hence some games (or applications) may +not work despite they should. + +The third reason is that no emulator support an easy way to switch +diskettes given a database of diskettes. With this emulator you can +easily switch diskettes through an intuitive interface. You can also +add additional information for each diskette (in your database), e.g. +which keys to use for a particular game program. The information is +kept in a plain text file that can be edited with an ordinary text +editor, preferbly GNU-Emacs. +(Aaron removed the above feature) + + +2. System files +=============== + +Before you can run the emulator, three vital system files must be +available. These are: + +apple_II.rom (12k) This file contains the ROM of your Apple II+. + It is not distributed due to copyright issues. + You have to get this file on your own. If you + have been running another emulator, you can + probably use its ROM files directly. Technically + speaking, this file is a memory dump of the + consecutive addresses from D000 to FFFF. This + file may also be called by other names such as + apple.rom or apple2.rom, but is referenced + internally as apple_II.rom. + +appple_IIe.rom Likewise for IIe emulation. + +slot6.rom (256 bytes) Memory dump of the consecutive addresses from + C600 to C6FF. This file is not distributed + either due to the same reasons as above. This + file may also be called by other names such as + controller.rom, but is referenced internally + as slot6.rom. + +Other important files +--------------------- + +.apple2 This file is distributed. The file contains default + parameter settings. The most important parameter is + the setting of the system path, i.e. the directory + where the three vital system (ROM) files are + stored. Most of the other parameters can be + changed during run time via the interface + (activated by pressing F10). + + Parameters (that can be set in .apple2): + + speed = % Speed of the emulator + path = Diskette database directory + color = off Monochrome mode + on Plain color mode + interpolated Interpolated color mode + sound = off Silent mode + pc speaker Sound through PC speaker + joystick = off Joystick disabled + linear Linear joystick mode + pc joystick PC Joystick (see CHANGES) + digital (Atari) digital joystick mode + not yet supported + joystick range 1-256 range of joystick + origin_x = 0-255 Origin of the joystick (X) + origin_y = 0-255 Origin of the joystick (Y) + sensitivity % Joystick sensitivity + system_path = Directory where the system + ROM files are stored. + pc joystick parms You don't want to fool + around with these, you + generate these parms from + F10 screen "Calibrate" menu + item. + +dsk.info An example is distributed. This file contains + information for various diskettes kept in the database. + + Syntax: + {} i.e. the name is written + within curly braces. + + + {} ... etc. + +3. Keyboard & keys +================== + +F1 To switch diskettes in Drive A, Slot 6 +F2 To switch diskettes in Drive B, Slot 6 +F4, also Pause key Pause +F5 Keyboard layout +F8 Words from the author (removed) +F9 Toggle between maximum speed and configured speed. +F10 General parameter settings +Break (ctrl-Pause) Apple II Reset key +Ctrl Printscreen Reboot Apple II emulator + +The numeric keypad is used for joystick emulation. + +Left Alt Joystick button 0 +Right Alt Joystick button 1 +Insert Joystick button 2 + +F7 Debugger - (if it's compiled into the source). + Edit the Makefile if you don't want the + debugger. The emulator will run slightly + faster without the debugger. + + +4. Diskette database +==================== + +The diskettes are provided as plain binary files. These are actually +raw dumps, containing the tracks from 0 to 34. For the standard +143360 byte .dsk format each track is partitioned into sectors +numbered from 0 to 15. Each sector is 256 bytes. Hence, the data is +organized as the following: + +File offset (in bytes) Sector Track +---------------------- ------ ----- +0 0 0 +256 1 0 +512 2 0 +. . . +. . . +. . . +3840 15 0 +4096 0 1 +4352 1 1 +. . . +. . . +. . . +143104 15 34 + +To transfer Apple II diskettes into this format requires that you own +an original Apple II. Since the drives provided by the IBM PC's are +not compatible with the original Apple II drives there are no +conversion programs directly available. If you have used other Apple +II emulators it is most likely that the files will work with this +emulator too. It seems to be a common standard to structure the +diskettes in the above described way, e.g. the ApplePC and Apl2em +emulators for DOS uses the same structure. + +Emulated diskettes MUST have the .dsk or .nib extension (143360 bytes +or 232960 bytes respectively), otherwise the emulator will not +recognize the file as a valid diskette. However, it is valid to +compress them by using gnu-zip (then the extension becomes .dsk.gz or +.nib.gz). The emulator will automatically decompress/compress them +whenever required (note that it assumes /bin/gzip exists). + +Note that you can add information/documentation for the dsk-diskettes +by using an ordinary text editor and edit the file "dsk.info". The +name of the diskette is written in curly braces (without the .dsk +extension) followed by any information. + + +5. Future plans +=============== + +I intend to improve the emulator. Actually, for the next major release +(i.e. version 1.00) the emulator will be entirely rewritten. For minor +changes, see file CHANGES. + +[Note from Stephen Lee: since this hasn't happened yet, I took to + improving the existing emulator until Alexander release a new one.] + +[Note from Aaron Culliney: since this still hasn't happened, I also +took the liberty to fix a few things and add some functionality.] + +[v004 note: decided to add in some more features, and fix problems as +they've arisen.] + +6. Status of the current emulator +================================= + +Works in standard VGA Y +Works in SVGA (then using SVGA facilities) Y +Disk drive emulation (slot 6) (.dsk & .nib) Y +Disk drive emulation (slot 5) N (release 1.00) +High resolution emulation Y +Low resolution emulation Y +Mixed mode (in all resolution modes) Y +Correct color emulation (both Low and Hi-res) Y +Interpolated color emulation Y +Configurable speed Y +Diskette switching Y +Diskette database Y +Interface for parameter settings, etc. Y +Sound emulation (PC speaker) Y +Flashing text Y +Joystick emulation through numeric keypad Y +Virtual console switching Y (only when emu. is paused) +Raw keyboard mode (reading scancodes) Y +Undocumented 6502 instructions Y +Language card (i.e. additonal 16k RAM) Y +Serial card N (maybe release 1.00) +Works on DOS N (AND NEVER WILL) +Apple II Debugger Y +PC Joystick kernel module support Y + +7. Can you port this to DOS? +============================ + +No, for two reasons. The first, and probably the most important, is +that the current emulator use kernel specific issues that are not, and +never will be, available in DOS. Future emulators will be based on the +same principles, so the emulator will never run in DOS. The second +reason is that DOS is a bad operating system. It is a pain in the neck +to write and debug programs in DOS and there is no usable memory +management provided by the kernel (if the DOS "interrupts" can be +called a "kernel" at all). + +With this free software I hope that more users will switch to Linux +(which is a great operating system) and I have a dream that one day, +DOS will become a minority. + +8. Availability +=============== + +This distribution is available at ftp.apple.asimov.net, and +tsx-11.mit.edu, and sites mirroring these. + +9. Known problems +================= + +Problem: SVGAlib version 1.2.8 and below has a bug in + keyboard-handling that makes the '-' key (in the emulator) + unusable. + +Solution: Please use SVGAlib version 1.2.9 or above. + +Problem: The REPT (repeat) key repeats too fast. + +Answer: The current implementation is a kludge by me [Stephen]. I + might fix it later, but again, I might not. + +Problem: I can't switch virtual consoles while running the program + under gdb [Aaron]. + +Answer: Actually you do, it's just that the graphic mode stays valid. + If you have the svgalib utility "textmode", try a "shell + textmode" reset. I haven't played around enough to figure out + how/if you can get back to graphic mode after this. + +Problem: Compiling with optimization causes the debugger to choke + [Aaron]. + +Answer: I'm playing fast and loose with the debugger's assembly hooks. + I think it's something to do with -fomit-frame-pointer. And + since I don't see much speed gain, I'm ignoring the problem + for now. + +10. Changes +=========== + +see file CHANGES + + +11. Final words +=============== + +Note that albeit you can switch between digital and linear joystick +emulation, only linear mode is presently supported. I still haven't +figured out how the atari (digital) joystick emulation works, so I'll +save it to the next release (as I said in the previous release :-) ) + +[PC Joystick mode is just another linear mode. In general linear mode +seems to work fine for most games. If a game seems to be having +trouble with it, change the range from $100 (256) to $80 (128) with +center points at $80 and $40 respectively. Switching around ranges +often seems to do the trick for most games, but I bet I'm not handling +the joystick softswich values correctly. documentation on this is +scant. -Aaron] + +I hope you will enjoy this emulator. I do. Many games (that I have +ported) works perfectly, even those that use undocumented 6502 +instructions. Suggestions to improvements are welcome. My email +address will be valid at least one more year, i.e. as long as I am a +computer science student at the University of Uppsala in Sweden. + + / Alexander Jean-Claude Bottema (Email: d91a1bo@meryl.csd.uu.se) + Oct. 9 1994 15:44:21 diff --git a/README.debugger b/README.debugger new file mode 100644 index 00000000..9e182aa9 --- /dev/null +++ b/README.debugger @@ -0,0 +1,154 @@ +************************************************************************* +* * +* Apple II debugger routines for the Linux-x86 Apple II emulator. * +* by Aaron Culliney - chernabog@baldmountain.bbn.com - (C) 1998 * +* * +* My code changes have nothing to do with my employer, GTE * +* Internetworking, BBN Technologies. They were written completely on my* +* own time and on my own machine. * +* * +************************************************************************* + +The debugger console is a mid-size hack onto the main emulator code. +I did it b/c I wanted to fool around with some of my old games while +they were running and to debug the emulator itself. +The code is kinda ugly in some areas, but seems robust enough; (I've +used flex to handle most of the dangerous UI stuff). It runs a bit +slower than when you're in unrestricted emulation mode because it's +doing a lot of switching between C code and asm, copying state, and +checking breakpoints/watchpoints. + + +KNOWN PROBLEMS: +-------------- + +When you hit a watchpoint or breakpoint, you have to step over it +before you can use the g{o}, f{inish}, or u{ntil} commands again. + +---------------------------------------------------------------------------- + +Usage: +----- + +F7 - enters the debugger. (actually we wait until we've finished with +the current 6502 instruction before we enter the debugger so we're all +synched up if/when we start stepping the machine). + +ESC - exits the debugger console. + +General Command format: + + command {optional part} (this | that) + +---------------------------------------------------------------------------- +Disassembling Apple II main memory and language card memory: + + d{is} {language card bank} {/bank/}{addrs} {+}{len} + + Examples: + "d" - disassemble from current location + "dis +5" - disassemble from current location +5 + "dis /01/2000" - (128k (//e) specific) + "dis lc1 d000 5" - disassemble memory +5 at lang card 1 0xd000 + +Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language +card. + +---------------------------------------------------------------------------- +Dumping memory: + + m{em} {lc1|lc2} {addrs} {+}{len} + a{scii} {lc1|lc2} {addrs} {+}{len} + + Examples: + + "mem" - dump memory at current location + "m dead" - dump memory at 0xDEAD + "m lc2 2fff 1" - dump memory at lang card 2 0x2FFF +1 + "ascii /01/400" - (128k (//e) specific) + +Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language +card. Also you need to specify the {addrs} if you're examining lc +memory. + +---------------------------------------------------------------------------- +Setting memory: + {lc1|lc2} : + + "4000:deadc0de" - set memory at 0x4000 to 0xDEADC0DE + "50lc2:def" - set memory at lang bank 2 0x50 to 0xDE0F + +Note: {addrs} can be (d000 <-> ffff) or (0 <-> 2fff) for the language +card. + +---------------------------------------------------------------------------- +Displaying machine state (registers, language card, drive, softswitches): + + r{egs} - registers + l{ang} - language card settings + dr{ive} - disk drive settings + vm - other virtual machine settings + +---------------------------------------------------------------------------- +Stepping the machine: + + (s{tep} | n{ext}) {len} + f{inish} + u{ntil} + g{o} {addr} + +-*step* or *next* 0-255 instructions. + +-*finish* current stack-frame (stop at RTS). + +-step *until* PC == next instruction (good for finishing loops). + +-*go* or jump to {addr} and continue executing until user hits a key. + +---------------------------------------------------------------------------- +Searching and setting/unsetting memory breakpoints and watchpoints: + + sea{rch} {lc1|lc2} + + "se deadc0de" - search for 0xDEADC0DE + "search lc2 def" - search lang bank2 (and lang card) for 0xDEF + + (b{reak} | w{atch}) {addr} + br{eak} op + (c{lear} | i{gnore}) {num} + c{lear} op + sta{tus} - show status of memory watch/breakpoints + op{codes} - show opcodes that we're stopping at + + "w c0e9" - watch memory at C0E9 + "br" - break at current PC + "br op 20" - break on opcode 20 + "clear 1" - clear breakpoint 1 + "ig" - ignore all watchpoints + "cl op 20" - clear break on opcode 20 + +-break or watch addrs. (use in conjunction with g{o}) + +-clear breakpoints, ignore watchpoints. + +-show break and watchpoint status. + +Note: breakpoints and watchpoints persist even when you exit the +debugger console. They are only reset if you clear/ignore them or +virtually reboot. + + +---------------------------------------------------------------------------- +Loading and saving state: + + bload + bsave // + + bload binary 8000 - load file into memory + bsave pic /0/2000 2000 - save memory to file + + +---------------------------------------------------------------------------- +Miscellaneous: + + fr{esh} - clear screen of graphics diff --git a/TODO b/TODO new file mode 100644 index 00000000..4ba59bb5 --- /dev/null +++ b/TODO @@ -0,0 +1,12 @@ +Obviously this emulator could use extension. We could do with support +for more disk-image formats, additional interface cards, memory-image +save/restore, and other things. + +However, most of these things would require hooking into parts of the code +that are likely going to change radically in later versions of the +emulator, due to badly needed cleanups. Thus, I do not recommend trying +to extend this version alone. + +If you want to work on the emulator, contact us first. We can give you alpha +versions of the emulator to work on, and coordinate your efforts with +other contributors. diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 00000000..9a901966 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,12 @@ +dnl This was cribbed from GNU libc (notice the symbol choices), but highly +dnl simplified since we can assume linking is working. +dnl A2_ASM_UNDERSCORES +AC_DEFUN(A2_ASM_UNDERSCORES,[ +AC_CACHE_CHECK(for _ prefix on C symbol names, a2_cv_asm_underscores, + [AC_TRY_LINK([asm ("_glibc_foobar:");], [glibc_foobar ();], + a2_cv_asm_underscores=yes, + a2_cv_asm_underscores=no)]) +if test $a2_cv_asm_underscores = no; then + AC_DEFINE(NO_UNDERSCORES) +fi +]) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..67b2ac1d --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,117 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +dnl This was cribbed from GNU libc (notice the symbol choices), but highly +dnl simplified since we can assume linking is working. +dnl A2_ASM_UNDERSCORES +AC_DEFUN(A2_ASM_UNDERSCORES,[ +AC_CACHE_CHECK(for _ prefix on C symbol names, a2_cv_asm_underscores, + [AC_TRY_LINK([asm ("_glibc_foobar:");], [glibc_foobar ();], + a2_cv_asm_underscores=yes, + a2_cv_asm_underscores=no)]) +if test $a2_cv_asm_underscores = no; then + AC_DEFINE(NO_UNDERSCORES) +fi +]) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + diff --git a/configure b/configure new file mode 100755 index 00000000..b051797b --- /dev/null +++ b/configure @@ -0,0 +1,2608 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-debugger Single-step, &c. support" +ac_help="$ac_help + --with-x use the X Window System" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=src/apple2.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:560: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:613: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:670: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=apple2-emul + +VERSION=0.7.4 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:716: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:729: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:742: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:755: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:768: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:785: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:815: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:866: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:898: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 909 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:940: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:945: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:973: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1006: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1027: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1044: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1061: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +ac_safe=`echo "linux/joystick.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/joystick.h""... $ac_c" 1>&6 +echo "configure:1087: checking for linux/joystick.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + + cat >> confdefs.h <<\EOF +#define PC_JOYSTICK 1 +EOF + + JOYSTICK_O=joystick.o +else + echo "$ac_t""no" 1>&6 +fi + + +# Check whether --enable-debugger or --disable-debugger was given. +if test "${enable_debugger+set}" = set; then + enableval="$enable_debugger" + + cat >> confdefs.h <<\EOF +#define DEBUGGER 1 +EOF + + DEBUGGER_O="debug.o debugger.o opcodes.o" +fi + + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1140: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1150: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1179: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1232: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1380: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + +echo $ac_n "checking for _ prefix on C symbol names""... $ac_c" 1>&6 +echo "configure:1404: checking for _ prefix on C symbol names" >&5 +if eval "test \"`echo '$''{'a2_cv_asm_underscores'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + a2_cv_asm_underscores=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + a2_cv_asm_underscores=no +fi +rm -f conftest* +fi + +echo "$ac_t""$a2_cv_asm_underscores" 1>&6 +if test $a2_cv_asm_underscores = no; then + cat >> confdefs.h <<\EOF +#define NO_UNDERSCORES 1 +EOF + +fi + + +# If we find X, set shell vars x_includes and x_libraries to the +# paths, otherwise set no_x=yes. +# Uses ac_ vars as temps to allow command line to override cache and checks. +# --without-x overrides everything else, but does not touch the cache. +echo $ac_n "checking for X""... $ac_c" 1>&6 +echo "configure:1442: checking for X" >&5 + +# Check whether --with-x or --without-x was given. +if test "${with_x+set}" = set; then + withval="$with_x" + : +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else +if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=NO ac_x_libraries=NO +rm -fr conftestdir +if mkdir conftestdir; then + cd conftestdir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat > Imakefile <<'EOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +EOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; do + if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && + test -f $ac_im_libdir/libX11.$ac_extension; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case "$ac_im_incroot" in + /usr/include) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; + esac + case "$ac_im_usrlibdir" in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; + esac + fi + cd .. + rm -fr conftestdir +fi + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1509: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + # Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done +fi +rm -f conftest* +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ + /usr/X11/lib \ + /usr/X11R6/lib \ + /usr/X11R5/lib \ + /usr/X11R4/lib \ + \ + /usr/lib/X11 \ + /usr/lib/X11R6 \ + /usr/lib/X11R5 \ + /usr/lib/X11R4 \ + \ + /usr/local/X11/lib \ + /usr/local/X11R6/lib \ + /usr/local/X11R5/lib \ + /usr/local/X11R4/lib \ + \ + /usr/local/lib/X11 \ + /usr/local/lib/X11R6 \ + /usr/local/lib/X11R5 \ + /usr/local/lib/X11R4 \ + \ + /usr/X386/lib \ + /usr/x386/lib \ + /usr/XFree86/lib/X11 \ + \ + /usr/lib \ + /usr/local/lib \ + /usr/unsupported/lib \ + /usr/athena/lib \ + /usr/local/x11r5/lib \ + /usr/lpp/Xamples/lib \ + /lib/usr/lib/X11 \ + \ + /usr/openwin/lib \ + /usr/openwin/share/lib \ + ; \ +do + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest* +fi # $ac_x_libraries = NO + +if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" +fi +fi + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$ac_t""$have_x" 1>&6 + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes \ + ac_x_includes=$x_includes ac_x_libraries=$x_libraries" + echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6 +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + cat >> confdefs.h <<\EOF +#define X_DISPLAY_MISSING 1 +EOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + case "`(uname -sr) 2>/dev/null`" in + "SunOS 5"*) + echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 +echo "configure:1691: checking whether -R must be followed by a space" >&5 + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_R_nospace=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_nospace=no +fi +rm -f conftest* + if test $ac_R_nospace = yes; then + echo "$ac_t""no" 1>&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_R_space=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_R_space=no +fi +rm -f conftest* + if test $ac_R_space = yes; then + echo "$ac_t""yes" 1>&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$ac_t""neither works" 1>&6 + fi + fi + LIBS="$ac_xsave_LIBS" + esac + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And karl@cs.umb.edu says + # the Alpha needs dnet_stub (dnet does not exist). + echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 +echo "configure:1756: checking for dnet_ntoa in -ldnet" >&5 +ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 +echo "configure:1797: checking for dnet_ntoa in -ldnet_stub" >&5 +ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldnet_stub $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to dickey@clark.net. + echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:1845: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1873: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_gethostbyname = no; then + echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:1894: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says simon@lia.di.epfl.ch: it contains + # gethostby* variants that don't use the nameserver (or something). + # -lsocket must be given before -lnsl if both are needed. + # We assume that if connect needs -lnsl, so does gethostbyname. + echo $ac_n "checking for connect""... $ac_c" 1>&6 +echo "configure:1943: checking for connect" >&5 +if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_connect) || defined (__stub___connect) +choke me +#else +connect(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_connect=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_connect=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_connect = no; then + echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 +echo "configure:1992: checking for connect in -lsocket" >&5 +ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. + echo $ac_n "checking for remove""... $ac_c" 1>&6 +echo "configure:2035: checking for remove" >&5 +if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_remove) || defined (__stub___remove) +choke me +#else +remove(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2063: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_remove=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_remove=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_remove = no; then + echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 +echo "configure:2084: checking for remove in -lposix" >&5 +ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lposix $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +else + echo "$ac_t""no" 1>&6 +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo $ac_n "checking for shmat""... $ac_c" 1>&6 +echo "configure:2127: checking for shmat" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shmat) || defined (__stub___shmat) +choke me +#else +shmat(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2155: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shmat=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shmat=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + + if test $ac_cv_func_shmat = no; then + echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 +echo "configure:2176: checking for shmat in -lipc" >&5 +ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lipc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +else + echo "$ac_t""no" 1>&6 +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS="$LDFLAGS" + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. + echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 +echo "configure:2228: checking for IceConnectionNumber in -lICE" >&5 +ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +else + echo "$ac_t""no" 1>&6 +fi + + LDFLAGS="$ac_save_LDFLAGS" + +fi + + +if test -z $no_x +then + PROGS="xapple2 xapple2-80col" +fi + +echo $ac_n "checking for vga_init in -lvga""... $ac_c" 1>&6 +echo "configure:2278: checking for vga_init in -lvga" >&5 +ac_lib_var=`echo vga'_'vga_init | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lvga $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + PROGS="$PROGS apple2" +else + echo "$ac_t""no" 1>&6 +fi + + +# unconditionally enabling //e support. No reason to do without it, IMO +cat >> confdefs.h <<\EOF +#define APPLE_IIE 1 +EOF + +cat >> confdefs.h <<\EOF +#define MAX_APPLE_DELAY 1000 +EOF + + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile src/Makefile disks/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@X_CFLAGS@%$X_CFLAGS%g +s%@X_PRE_LIBS@%$X_PRE_LIBS%g +s%@X_LIBS@%$X_LIBS%g +s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g +s%@JOYSTICK_O@%$JOYSTICK_O%g +s%@DEBUGGER_O@%$DEBUGGER_O%g +s%@PROGS@%$PROGS%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..bd85ca83 --- /dev/null +++ b/configure.in @@ -0,0 +1,35 @@ +AC_INIT(src/apple2.h) +AM_INIT_AUTOMAKE(apple2-emul, 0.7.4) + +AC_PROG_CC + +AC_CHECK_HEADER(linux/joystick.h, [ + AC_DEFINE(PC_JOYSTICK) + JOYSTICK_O=joystick.o]) + +AC_ARG_ENABLE(debugger, [ --enable-debugger Single-step, &c. support],[ + AC_DEFINE(DEBUGGER) + DEBUGGER_O="debug.o debugger.o opcodes.o"]) + +AC_FUNC_MMAP +A2_ASM_UNDERSCORES + +AC_PATH_XTRA + +if test -z $no_x +then + PROGS="xapple2 xapple2-80col" +fi + +AC_CHECK_LIB(vga,vga_init,PROGS="$PROGS apple2") + +# unconditionally enabling //e support. No reason to do without it, IMO +AC_DEFINE(APPLE_IIE) +AC_DEFINE(MAX_APPLE_DELAY,1000) + +AC_SUBST(JOYSTICK_O) +AC_SUBST(DEBUGGER_O) +AC_SUBST(PROGS) + +AC_OUTPUT([Makefile src/Makefile disks/Makefile]) + diff --git a/disks/Makefile.am b/disks/Makefile.am new file mode 100644 index 00000000..7a5fba6b --- /dev/null +++ b/disks/Makefile.am @@ -0,0 +1,5 @@ +# we may want to change this to pkgdata_DATA, to automatically install +# the disk images. + +EXTRA_DIST = README blank.dsk.gz blank.nib.gz etc.dsk.gz mystery.dsk.gz \ + speedtest.dsk.gz speedtest.txt diff --git a/disks/Makefile.in b/disks/Makefile.in new file mode 100644 index 00000000..c52a6961 --- /dev/null +++ b/disks/Makefile.in @@ -0,0 +1,173 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# we may want to change this to pkgdata_DATA, to automatically install +# the disk images. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +DEBUGGER_O = @DEBUGGER_O@ +JOYSTICK_O = @JOYSTICK_O@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +PROGS = @PROGS@ +VERSION = @VERSION@ + +EXTRA_DIST = README blank.dsk.gz blank.nib.gz etc.dsk.gz mystery.dsk.gz speedtest.dsk.gz speedtest.txt + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_COMMON = README Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps disks/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = disks + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/disks/README b/disks/README new file mode 100644 index 00000000..ebce7229 --- /dev/null +++ b/disks/README @@ -0,0 +1,22 @@ +Sample Disk Images +------ ---- ------ + +These disk images are merely distributed with the emulator and are not +actually part of it. (ie: not subject to GPL, and not written by us.) + +Many more disk images (including ones we'd never include here due to +copyright considerations) may be found on ftp.apple.asimov.net. + +blank.dsk.gz - +blank.nib.gz - + Blank DOS3.3-formatted disk images. + +etc.dsk.gz - + A disk with miscellaneous programs, and apparently an assembler. + +mystery.dsk.gz - + Sierra's old Mystery House game, now freely distributable. + +speedtest.dsk.gz - + William Night's emulator benchmarks. + diff --git a/disks/blank.dsk.gz b/disks/blank.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..e09655155857d56821ce8a7e99be1f6753b044ae GIT binary patch literal 7335 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 P6HSdJ2=4{Ys~7(R`JgkK literal 0 HcmV?d00001 diff --git a/disks/blank.nib.gz b/disks/blank.nib.gz new file mode 100644 index 0000000000000000000000000000000000000000..34614dc300c031be2a6fcb6649aeb0e4cfd5aa67 GIT binary patch literal 12992 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 USF4UbhMki<+(RYdMB(E6FKa$$(*OVf literal 0 HcmV?d00001 diff --git a/disks/etc.dsk.gz b/disks/etc.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..3013e1756e7ca2b11f6934b51a76d3b523e39aec GIT binary patch literal 28592 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 P;DD4mJ1zhV7~uZ^pAb=g literal 0 HcmV?d00001 diff --git a/disks/speedtest.dsk.gz b/disks/speedtest.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..eacf34bc737f16456c847c2da3d9bfa2c2788ec9 GIT binary patch literal 15153 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 +NNTP-Posting-Host: espresso.cafe.net +X-Newsreader: TIN [version 1.2 PL2] + +These are the latest results from SpeedTest 2.2.2 + + AplWin2 Sim2e Apl2em-2 Applemu +Test +CPU-Index 6.472 3.155 8.532 11.47 +TEXT-Index 2.629 0.1957 4.470 6.274 +VIDEO-Index 1.388 0.1957 3.990 5.271 +DISK-Index 3.297 0.4715 5.690 0.9626 + +I will post the results from all the tests as soon as I get around to +typing it in. These highlight the actual strengths and weaknesses of +each emulator and are usefull in figuring out how fast an emulator will +run a certain class of programs. + +The tests used will remain the same for each minor version level. All +patch-level changes 2.2.x etc will just be to the main program and the +results will be the same as all other patch levels with the same major +and minor versions. For example the results for 2.2.2 and 2.2.8 will be +the same, while the results between 2.2.2 and 2.3.2 are not gauranteed +to be. + +These results were obtained on a 486dx4/100 with 4-Dos and QEMM loaded, +the AplWin tests were performed in Windows 3.1 with the appropriate +Win32 extensions added. I have a cirrus logic 5426 1MB VLB card +installed. + +My system tests out at 195.7 in Sysinfo from Norton. I don't have any +Video benchmarks that are common enough that the results would mean +anything (see #1 below) + +A few comments about the results. + +1) Until I get a benchmark program for the machine the emulator is +running on that all people involved can agree on, test results do not mean +anything between platforms or even between two of the same type of machines +running at different speeds. The only way the results should be used is to +compare the relative speeds of two emulators on the same machine. + +2) The relative speeds compared to a //e do not mean that the emulator +will perform that quickly or slowly on a video game or other +application, for example, Sim2e appears to be very slow, but plays games +quite well on my machine. The tests are very intensive in a specific +area, where most programs are more general in their use of system +resources. + +3) These tests aren't completely fair. The CPU tests are for the most +part, but differences in the way an emulator is implemented make certain +things automatically faster or slower. For instance, both Apl2em-2 and +Applemu use IBM text for the apple text screen, therefore all text +operations are handled by the IBM graphics card, both Sim2e and AplWin2 +do their own translation of text to graphics (and achieve a much more +realistic looking screen). With the video tests, Applemu will only do +black-and-white high-res graphics. This gives it an unfair advantage +over the others. + + +Any suggestions for the next version of speed-test or comments or +questions are welcome. + +The new version of SpeedTest will be posted in the next message, and will +probably make it's way onto an FTP site soon. + + + diff --git a/install-sh b/install-sh new file mode 100755 index 00000000..e8436696 --- /dev/null +++ b/install-sh @@ -0,0 +1,250 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/missing b/missing new file mode 100755 index 00000000..cbe2b0ef --- /dev/null +++ b/missing @@ -0,0 +1,188 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in` + if test -z "$files"; then + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in` + test -z "$files" || files="$files.in" + else + files=`echo "$files" | sed -e 's/:/ /g'` + fi + test -z "$files" && files="config.h.in" + touch $files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print \ + | sed 's/^\(.*\).am$/touch \1.in/' \ + | sh + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 00000000..a01481be --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..bef715bd --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,77 @@ +noinst_HEADERS = apple2.h debug.h disk.h interface.h keys.h misc.h \ + video.h cpu.h glue.h gluepro.h prefs.h + +SUFFIXES = .l-cpp -80.o + +man_MANS = apple2.6 + +EXTRA_PROGRAMS = apple2 xapple2 xapple2-80col +bin_PROGRAMS = @PROGS@ + +EXTRA_apple2_SOURCES = debugger.c opcodes.c debug.c joystick.c +apple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c \ + interface.c misc.c font.c svideo.c compact.c cpu-supp.c \ + vidsup.c + +apple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ -lvga +apple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ + +EXTRA_xapple2_SOURCES = debugger.c opcodes.c debug.c joystick.c + +xapple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c \ + disk.c interface.c misc.c font.c xvideo.c compact.c \ + cpu-supp.c vidsup.c + +xapple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ @X_LIBS@ -lX11 -lXext +xapple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ + +EXTRA_xapple2_80col_SOURCES = debugger.c opcodes.c debug.c joystick.c + +xapple2_80col_SOURCES = cpu.S memory.S glue.S keys.c prefs.c disk.c \ + font.c compact.c cpu-supp.c misc.c interface.c + +xapple2_80col_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ \ + vidsup-80.o xvideo-80.o display-80.o \ + @X_LIBS@ -lX11 -lXext +xapple2_80col_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ \ + vidsup-80.o xvideo-80.o display-80.o + +noinst_PROGRAMS = genfont + +BUILT_SOURCES = font.c debug.c glue.S + +EXTRA_DIST = font.txt apple2.6 debug.l-cpp genglue + +CLEANFILES = font.c debug.c glue.S + +# Warning: this will trip on a cross-compile +# (not that we're otherwise portable to non-Linux yet...) +font.c : font.txt genfont + ./genfont < $< > $@ + +glue.S : disk.c misc.c + $(srcdir)/genglue $^ > $@ + +%-80.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $< + +display-80.o: display.S + $(CC) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $< + +# I couldn't get Automake's internal Lex support to work with this, as +# Automake assumes the program was built to cope with no -P option. These +# files require it and also need preprocessing. +# +# Of course this is really our fault for being nonportable to standard Lex... +# (which I presume has no -P) + +%.c: %.l-cpp + $(CC) -x c -E -P $(CPPFLAGS) $(DEFS) $< | flex -i -P$* -o$@ + + +# Another hack. I can't see any other way to get across to automake that some +# built sources should not be distributed. (since they vary with +# configuration) + +dist-hook: + rm -f $(distdir)/font.c $(distdir)/debug.c $(distdir)/glue.S diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..1817ee09 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,433 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +DEBUGGER_O = @DEBUGGER_O@ +JOYSTICK_O = @JOYSTICK_O@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +PROGS = @PROGS@ +VERSION = @VERSION@ + +noinst_HEADERS = apple2.h debug.h disk.h interface.h keys.h misc.h video.h cpu.h glue.h gluepro.h prefs.h + + +SUFFIXES = .l-cpp -80.o + +man_MANS = apple2.6 + +EXTRA_PROGRAMS = apple2 xapple2 xapple2-80col +bin_PROGRAMS = @PROGS@ + +EXTRA_apple2_SOURCES = debugger.c opcodes.c debug.c joystick.c +apple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c interface.c misc.c font.c svideo.c compact.c cpu-supp.c vidsup.c + + +apple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ -lvga +apple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ + +EXTRA_xapple2_SOURCES = debugger.c opcodes.c debug.c joystick.c + +xapple2_SOURCES = cpu.S memory.S display.S glue.S keys.c prefs.c disk.c interface.c misc.c font.c xvideo.c compact.c cpu-supp.c vidsup.c + + +xapple2_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ @X_LIBS@ -lX11 -lXext +xapple2_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ + +EXTRA_xapple2_80col_SOURCES = debugger.c opcodes.c debug.c joystick.c + +xapple2_80col_SOURCES = cpu.S memory.S glue.S keys.c prefs.c disk.c font.c compact.c cpu-supp.c misc.c interface.c + + +xapple2_80col_LDADD = @DEBUGGER_O@ @JOYSTICK_O@ vidsup-80.o xvideo-80.o display-80.o @X_LIBS@ -lX11 -lXext + +xapple2_80col_DEPENDENCIES = @DEBUGGER_O@ @JOYSTICK_O@ vidsup-80.o xvideo-80.o display-80.o + + +noinst_PROGRAMS = genfont + +BUILT_SOURCES = font.c debug.c glue.S + +EXTRA_DIST = font.txt apple2.6 debug.l-cpp genglue + +CLEANFILES = font.c debug.c glue.S +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +apple2_OBJECTS = cpu.o memory.o display.o glue.o keys.o prefs.o disk.o \ +interface.o misc.o font.o svideo.o compact.o cpu-supp.o vidsup.o +apple2_LDFLAGS = +xapple2_OBJECTS = cpu.o memory.o display.o glue.o keys.o prefs.o disk.o \ +interface.o misc.o font.o xvideo.o compact.o cpu-supp.o vidsup.o +xapple2_LDFLAGS = +xapple2_80col_OBJECTS = cpu.o memory.o glue.o keys.o prefs.o disk.o \ +font.o compact.o cpu-supp.o misc.o interface.o +xapple2_80col_LDFLAGS = +genfont_SOURCES = genfont.c +genfont_OBJECTS = genfont.o +genfont_LDADD = $(LDADD) +genfont_DEPENDENCIES = +genfont_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man6dir = $(mandir)/man6 +MANS = $(man_MANS) + +NROFF = nroff +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(apple2_SOURCES) $(EXTRA_apple2_SOURCES) $(xapple2_SOURCES) $(EXTRA_xapple2_SOURCES) $(xapple2_80col_SOURCES) $(EXTRA_xapple2_80col_SOURCES) genfont.c +OBJECTS = $(apple2_OBJECTS) $(xapple2_OBJECTS) $(xapple2_80col_OBJECTS) genfont.o + +all: all-redirect +.SUFFIXES: +.SUFFIXES: -80.o .S .c .l-cpp .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps src/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +mostlyclean-noinstPROGRAMS: + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +distclean-noinstPROGRAMS: + +maintainer-clean-noinstPROGRAMS: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +apple2: $(apple2_OBJECTS) $(apple2_DEPENDENCIES) + @rm -f apple2 + $(LINK) $(apple2_LDFLAGS) $(apple2_OBJECTS) $(apple2_LDADD) $(LIBS) + +xapple2: $(xapple2_OBJECTS) $(xapple2_DEPENDENCIES) + @rm -f xapple2 + $(LINK) $(xapple2_LDFLAGS) $(xapple2_OBJECTS) $(xapple2_LDADD) $(LIBS) + +xapple2-80col: $(xapple2_80col_OBJECTS) $(xapple2_80col_DEPENDENCIES) + @rm -f xapple2-80col + $(LINK) $(xapple2_80col_LDFLAGS) $(xapple2_80col_OBJECTS) $(xapple2_80col_LDADD) $(LIBS) + +genfont: $(genfont_OBJECTS) $(genfont_DEPENDENCIES) + @rm -f genfont + $(LINK) $(genfont_LDFLAGS) $(genfont_OBJECTS) $(genfont_LDADD) $(LIBS) + +install-man6: + $(mkinstalldirs) $(DESTDIR)$(man6dir) + @list='$(man6_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.6*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man6dir)/$$inst; \ + done + +uninstall-man6: + @list='$(man6_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.6*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man6dir)/$$inst"; \ + rm -f $(DESTDIR)$(man6dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man6 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man6 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-binPROGRAMS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man6 + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-noinstPROGRAMS \ + mostlyclean-compile mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-binPROGRAMS clean-noinstPROGRAMS clean-compile \ + clean-tags clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-binPROGRAMS distclean-noinstPROGRAMS \ + distclean-compile distclean-tags distclean-generic \ + clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-noinstPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \ +clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile install-man6 uninstall-man6 install-man \ +uninstall-man tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Warning: this will trip on a cross-compile +# (not that we're otherwise portable to non-Linux yet...) +font.c : font.txt genfont + ./genfont < $< > $@ + +glue.S : disk.c misc.c + $(srcdir)/genglue $^ > $@ + +%-80.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $< + +display-80.o: display.S + $(CC) $(CPPFLAGS) $(DEFS) -D_640x400 -c -o $@ $< + +# I couldn't get Automake's internal Lex support to work with this, as +# Automake assumes the program was built to cope with no -P option. These +# files require it and also need preprocessing. +# +# Of course this is really our fault for being nonportable to standard Lex... +# (which I presume has no -P) + +%.c: %.l-cpp + $(CC) -x c -E -P $(CPPFLAGS) $(DEFS) $< | flex -i -P$* -o$@ + +# Another hack. I can't see any other way to get across to automake that some +# built sources should not be distributed. (since they vary with +# configuration) + +dist-hook: + rm -f $(distdir)/font.c $(distdir)/debug.c $(distdir)/glue.S + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/apple2.6 b/src/apple2.6 new file mode 100644 index 00000000..bda6b528 --- /dev/null +++ b/src/apple2.6 @@ -0,0 +1,301 @@ +.\" Apple ][ emulator manpage +.\" by Aaron Culliney - chernabog@baldmountain.bbn.com - (C) 1997-1998 +.\" +.\" apple2.6 - manpage which mostly echos README +.\" +.\" $Id: apple2.6,v 1.8 1998/08/25 03:00:00 chernabog Exp $ +.\" +.\" MODIFICATION HISTORY +.\" v0.5 by Aaron Culliney , Feb 1998. +.\" v0.6 by Aaron Culliney , Aug 1998. +.\" This code has nothing to do with my employer, GTE Internetworking, +.\" BBN Technologies. It was written completely on my own time and on +.\" my own machine. +.\" +.TH APPLE2 6 "31 August 1998" +.UC 7 +.SH NAME +apple2, xapple2 \- Apple ][+ and //e emulator +.SH SYNOPSIS +.ft B +apple2 +.PP +.ft B +xapple2 [ -noshm ] +.ft R +.SH DESCRIPTION +.I apple2 +(svgalib) and +.I xapple2 +(X11) both emulate a 64k Apple ][+ and 128k Apple //e computer (the latter +only if //e support +compiled in). To use the emulator you need to acquire the original +][+ and //e ROM files which are not distributed due to copyright +reasons. The emulator reads standard 143360-byte and 232960-byte disk +image files with +.I .dsk +and +.I .nib +suffixes respectively. +You can also change any images with the extension +.I .do +to +.I .dsk +and they will work too. +.PP +There are only a few command line options: +.TP +.I -noshm +This forces the X11 version to not use the MITSHM extension. This may degrade +the speed of the emulator but allow you to run it remote. +.PP +.ft R +.SH THE .apple2 FILE +The emulator reads user preferences from a +.I .apple2 +file located in your home directory. Copy the +.I .apple2 +file that comes distributed with the emulator to your home directory. +You can edit the settings using your favorite editor, but most of the +settings can be tweaked from within the emulator (see menus section below). +.TP +.I speed +Speed of emulation, 1 - XXX. (Actually this is an inverse delay-loop counter). 1 is +slow, and XXX is as fast as can be. +A delay loop is needed to bring the emulation rate down to near what would be +considered a normal Apple ][ speed. +The max speed value should be determined by +.I YOU +when you compile the emulator. +For <= 100Mhz Pentium systems, I personally +like a max value of 100 with a normal apple ][ speed somewhere in the 70s. +For faster machines, try larger ranges. +.TP +.I mode +Starting emulation mode. One of "][+", "][+ undocumented", "//e". You can +also dynamically change the emulation mode from within the emulator. +.TP +.I disk path +Toplevel path of disk images directory. Personally I like +/usr/local/games/apple2/disks. +.TP +.I color +Black/white, lazy color, color, lazy interpolated, interpolated. +.TP +.I sound +Off, pc speaker. +.TP +.I joystick +Off, linear, pc joystick. +.TP +.I joystick range +2 - 256. Range of the joystick values. Good settings are 256 and +sometimes 128, with centers at 128 and 64 respectively. This often depends on +the game. +.TP +.I origin_x +X coordinate origin. 128 is good for many games with a range of 256. Others +like 64 with a range of 128. +.TP +.I origin_y +Y coordinate origin. 128 is good for many games with a range of 256. Others +like 64 with a range of 128. +.TP +.I pc joystick parms +You can configure this from within the emulator. Select the 'Calibrate' +option from the F10 menu. If the emulator complains that +it cannot open the joystick device, make sure the module is loaded. +.I This option is only valid if you've compiled the emulator with -DPC_JOYSTICK. +.TP +.I sensitivity +1% - 100%. This value is used for the emulated joystick using the +numeric keypad. +.TP +.I system path +The directory holding the rom files. The emulator won't run if this +is not set properly. You can only change this by editing the +.I .apple2 +file. +.PP +So here is an example .apple2 file: +.nf + speed = 72 + mode = ][+ + disk path = /usr/local/games/apple2/disks + color = interpolated + sound = pc speaker + joystick = pc joystick + joystick range = 256 + origin_x = 128 + origin_y = 128 + pc joystick parms = 767 693 1344 28 1454 28 13 + sensitivity = 13% + system path = /usr/local/games/apple2/rom +.fi +.PP +.ft R +.SH ROM FILES +The emulator requires several ROM files to run. +.TP +.I apple_II.rom +You need this file for basic ][+ emulation. It contains the 12K ROM +of your Apple ][+. It is not distributed due to copyright issues, so +you have to get this file on your own. If you have been running +another apple2 emulator, you can most likely use its ROM files +directly. This file is a memory dump of the consecutive addresses +from D000 to FFFF of the Apple ][+. This file may also be named +.I apple.rom +or +.I apple2.rom, +but is referenced internally as +.I apple_II.rom. +.TP +.I slot6.rom +You need this file for basic disk drive emulation. It is 256 byte +memory dump of the consecutive addresses from C600 to C6FF. This file +is not distributed again due to copyright issues. This file may also +be named +.I controller.rom, +but is referenced internally as +.I slot6.rom. +.TP +.I apple_IIe.rom +If //e support was not compiled into the emulator, then you do not need this +file. +It is the 32K ROM of your 128k Apple //e, a dump of main memory (bank 0) +addresses C000-FFFF concatenated with auxiliary memory (bank 1) +addresses C000-FFFF. Because the +.I apple_IIe.rom +contains the C600 slot, you can construct the +.I slot6.rom +file from this one. The +.I apple_IIe.rom +file may also be named +.I apple2e.rom +but is referenced internally as +.I apple_IIe.rom. +.TP +.I character.rom +A 2048 byte ][+ character rom file. This file is distributed with the +emulator. +.PP +.ft R +.SH DISK IMAGES +The emulator reads standard DOS3.3-order 143360 byte '.dsk' images and +raw-nibble 232960 byte '.nib' images. The emulator can handle images +which are gzip'ed as long as the suffixes are '.dsk.gz' and '.nib.gz' +respectively. The emulator simply assumes that /bin/gzip is available +to compress/decompress these images in place as needed and that you have +permission to do so. +.PP +The images are raw binary dumps, containing the tracks from 0 to 34 +from the original 5.25 disk. For the standard 143360 byte '.dsk' +format each track is partitioned into sectors of 256 bytes, numbered +from 0 to 15. +.PP +The raw nibblized 232960-byte images are usually made of +programs that have non-standard formatting as a means of copy +protection. The nibblized format attempts to preserve the +non-standard format, and so defeats the copy protection without +"cracking" the program. +.PP +To transfer Apple ][ diskettes into one of these formats requires that +you own an original Apple ][. Since the drives provided by the IBM +PC's are not compatible with the original Apple ][ drives there are no +conversion programs directly available. If you have used other Apple +][ emulators it is most likely that the files will work with this +emulator too. For more information on Apple ][ disk formats and such, +see +.I Beneath Apple DOS +by Don Worth and Pieter Lechner, published long ago by Quality Software. +.PP +.ft R +.SH EMULATOR KEYS/MENUS +.TP +.I F1 +Interface to switch disk in Drive A, Slot 6. Arrow keys navigate the +selection. If the disk highlighted is already in the drive, it will +have a or tag after the name indicating read/write or +read-only access. Select this disk to eject it. To select a disk, +you can press 'w' or RETURN to insert it into the drive. Pressing 'w' +will attempt to open the disk as read/write (if you have permission to +do so). +Pressing RETURN defaults to opening the disk read-only. Press +ESC to accept current settings and exit the menu. +.TP +.I F2 +Interface to switch disk in Drive B, Slot 6. Same controls as for +.I F1. +.TP +.I F4 +Pause the emulation. The Pause/Break key will also work. Hit a key +to resume. +.TP +.I F5 +Display the Apple ][+ or //e keyboard layout. +.TP +.I F7 +Enter the Debugger console (if this support was compiled into the +program). See the file DEBUGGER that came with the emulator for +command information. +.TP +.I F9 +Toggles between maximum speed and configured speed. This is useful to 'fastboot' +programs, and then slip back to normal Apple ][ speed. +.TP +.I F10 +General parameter settings menu, including the all-important QUIT option. +You can edit most of the parameters in your +.I .apple2 +file from this menu. +Two options worth mentioning are +the 'Calibrate' and 'JS Sample' options. 'Calibrate' lets you +calibrate the PC Joystick device. 'JS Sample' lets you set the sample +rate of the PC Joystick device. 'Save' lets you save the settings to +your +.I .apple2 +file. +.TP +.I Special Keys +The key combination Ctrl-'PrintScrn/SysReq' will reboot the machine. +The Ctrl-'Pause/Break' combination will reset the machine. Remember +that 'Pause/Break' alone will pause emulation. AltLeft and AltRight +keys correspond to the OpenApple and ClosedApple keys (joystick +buttons 0 & 1). NOTE: In //e mode try Ctrl-AltRight-'Pause/Break' +sequence for a system self-test. The numeric keypad is used for +emulated joystick movement. +.ft R +.SH BUGS AND STUFF +See the PROBLEMS file that came with the code. +.PP +Using the joystick for some disk images is problematic. +Apparently there is a bug in Apple ]['s where reading values from the +joystick ports too quickly results in a smaller value than normal. +Unfortunately the emulator doesn't emulate this bug in the machine, +but you can mostly get the same +effect by changing the range of the joystick. For instance, games like Space +Rogue and Airheart like a range of 0x80 with the center around 0x40. Most +other games will like a range of 0x100 with the center around 0x80. +.PP +Under X, you may notice that some keys are not working as advertised +(Pause/Break as reboot for instance). Make sure that these keys are mapped. +(Run xmodmap -pke for the current mapping). +.ft R +.SH MORE INFO +More information is available in the online newsgroups +.I comp.emulators.apple2, +and +.I comp.sys.apple2. +.PP +See also: +.TP +.I Apple //e Technical Reference Manual +.TP +.I Beneath Apple DOS +.TP +.I Beneath Apple ProDOS +.ft R +.SH AUTHORS +Apple //e support and revisions v006, v005, v004, v003 by Aaron Culliney +(aculline@bbn.com). Revision v002 by Stephen Lee. Original version(s) +by Alexander Jean-Claude Bottema. diff --git a/src/apple2.h b/src/apple2.h new file mode 100644 index 00000000..32205995 --- /dev/null +++ b/src/apple2.h @@ -0,0 +1,38 @@ +/* + * Apple // emulator for Linux: Common definitions + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef A2_H +#define A2_H + +#define BANK2 0x10000 + +/* Code alignment */ +#if defined(__i486__) || defined(__i586__) +#define ALIGN .balign 16 +#else /* !(__i486__ || __i586__) */ +#define ALIGN .balign 4 +#endif /* !(__i486__ || __i586__) */ + +/* Symbol naming issues */ +#ifdef NO_UNDERSCORES +#define SN(foo) foo +#define E(foo) .globl foo ; ALIGN ; foo##: +#else /* !NO_UNDERSCORES */ +#define SN(foo) _##foo +#define E(foo) .globl _##foo ; ALIGN ; _##foo##: +#endif /* !NO_UNDERSCORES */ + +#endif/* A2_H */ diff --git a/src/compact.c b/src/compact.c new file mode 100644 index 00000000..80ebc67c --- /dev/null +++ b/src/compact.c @@ -0,0 +1,174 @@ +/* + * Apple // emulator for Linux: Memory optimizer + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include + +#include "misc.h" +#include "cpu.h" + +/* This code is not essential to emulator operation. It (ab)uses the + * virtual-memory system so that repetitive parts of the memory-access + * indirection table are compressed. This should hopefully relieve load + * on the processor's cache and boost speed. + * + * This file is far more complicated than it needs to be. For the present + * purpose --- emulating an Apple // series machine on an 386 box --- I + * could have hard-wired the compaction specifically for the Apple layout and + * i386 page size. + * + * But it's more flexible - it needs no change to be used in an emulator + * for Nintendo, C64, etc. Support for host processors with different + * page sizes will just be matter of changing the PSIZE and TPAGES macros. + * + */ + +#define TSIZE 524288 /* Size of the entire table */ +#define PSIZE 4096 /* Size of a page */ +#define TPAGES 128 /* pages in table */ + +#ifndef HAVE_MMAP + +void precompact(void){} +void compact(void){} + +#else /* HAVE_MMAP */ + +static int compaction_file = -1; + +void pre_compact(void) +{ + const char *tmpdir; + char *filename; + char *x; + + /* Destroy any old mapping file */ + close(compaction_file); + + /* Reset the mapping on the table to normal, in case compaction has + * been done before. This also tests if the kernel is advanced enough + * to support this stunt. + */ + x = mmap((void *) cpu65_vmem, + TSIZE, + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, + 0, + 0); + + if (x == MAP_FAILED) + { + /* mmap failed. + * For now we assume this is because we are running on a system + * which doesn't support cookie-cutter mmap operations. + * + * We set compaction_file to -1 and return. This tells compact to + * do nothing. (The emu still works.) + */ + printf("System does not appear to support fancy mmap\n" + "(error: %m)\n"); + + compaction_file = -1; + return; + } + + /* Create a fresh new mapping file */ + tmpdir = getenv("TMPDIR"); + if (!tmpdir) tmpdir = "/tmp"; + filename = alloca(strlen(tmpdir) + 9); + strcpy(filename,tmpdir); + strcat(filename,"/a2-XXXXXX"); + compaction_file = mkstemp(filename); + + if (!compaction_file) + { + fprintf(stderr,"cannot open temporary file (%m)\n"); + exit(EXIT_FAILURE); + }; + + unlink(filename); + ftruncate(compaction_file,TSIZE); /* might not be 100% portable */ + + /* If the ftruncate doesn't work (Single Unix does not require it + * to work for the extending case), try this instead: + * + * lseek(compaction_file,TSIZE-1,SEEK_SET); + * write(compaction_file,"",1); + */ + +} + +void compact(void) +{ + int i,j,n; + char *work; + char *x; + + /* Give up if the first mmap didn't work out */ + if (compaction_file == -1) return; + + work = mmap(0, + TSIZE, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_SHARED, + compaction_file, + 0); + + if (work == MAP_FAILED) + { + fprintf(stderr,"mmap failure (%m)"); + exit(EXIT_FAILURE); + } + + n = 0; + i = TPAGES; + + while (i--) + { + j = n; + while (j-- && memcmp(work+j*PSIZE, + ((void *) cpu65_vmem)+i*PSIZE, + PSIZE)); + if (j == -1) + { + memcpy(work+n*PSIZE, + ((void *) cpu65_vmem)+i*PSIZE, + PSIZE); + j = n++; + } + + x = mmap(((void *) cpu65_vmem)+i*PSIZE, + PSIZE, + PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_FILE|MAP_SHARED, + compaction_file, + j*PSIZE); + + if (work == MAP_FAILED) + { + fprintf(stderr,"mmap failure (%m)"); + exit(EXIT_FAILURE); + } + } + + munmap(work,TSIZE); + +} + +#endif /* HAVE_MMAP */ diff --git a/src/cpu-supp.c b/src/cpu-supp.c new file mode 100644 index 00000000..697d9b40 --- /dev/null +++ b/src/cpu-supp.c @@ -0,0 +1,88 @@ +/* + * Apple // emulator for Linux: C support for 6502 on i386 + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include + +#include "cpu.h" + +/* different than in defs.h! */ +#define C_Flag_6502 0x1 +#define X_Flag_6502 0x20 +#define I_Flag_6502 0x4 +#define V_Flag_6502 0x40 +#define B_Flag_6502 0x10 +#define D_Flag_6502 0x8 +#define Z_Flag_6502 0x2 +#define N_Flag_6502 0x80 + +static void initialize_code_tables(void) +{ + int i; + + for (i = 0; i < 256; i++) + { + unsigned char val = 0; + + if (i & C_Flag) + val |= C_Flag_6502; + if (i & X_Flag) + val |= X_Flag_6502; + if (i & I_Flag) + val |= I_Flag_6502; + if (i & V_Flag) + val |= V_Flag_6502; + if (i & B_Flag) + val |= B_Flag_6502; + if (i & D_Flag) + val |= D_Flag_6502; + if (i & Z_Flag) + val |= Z_Flag_6502; + if (i & N_Flag) + val |= N_Flag_6502; + + cpu65_flags_encode[ i ] = val | 0x20; + cpu65_flags_decode[ val ] = i; + } +} + + +void cpu65_set(int flags) +{ + initialize_code_tables(); + + switch (flags & 0xf) + { + case CPU65_NMOS: + if (flags & CPU65_FAULT) + memcpy(cpu65__opcodes,cpu65__nmosbrk,1024); + else + memcpy(cpu65__opcodes,cpu65__nmos,1024); + break; + case CPU65_C02: + memcpy(cpu65__opcodes,cpu65__cmos,1024); + break; + default: + abort(); + } + + cpu65__signal = 0; +} + +void cpu65_interrupt(int reason) +{ + cpu65__signal = reason; +} + diff --git a/src/cpu.S b/src/cpu.S new file mode 100644 index 00000000..d4e8a259 --- /dev/null +++ b/src/cpu.S @@ -0,0 +1,3348 @@ +/* + * Apple // emulator for Linux: Virtual 6502/65C02 + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include "apple2.h" +#include "cpu.h" +#include "misc.h" + + .comm SN(cpu65_vmem),524288,4096 + .comm SN(cpu65_flags_encode),256 + .comm SN(cpu65_flags_decode),256 + .comm SN(cpu65_delay),4 + .comm SN(cpu65__opcodes),1024 + .comm SN(cpu65__signal),1 + .comm SN(cpu65_debug),4 + .comm SN(cpu65_current),7 + +/* ------------------------------------------------------------------------- + CPU (6502) Helper Routines + ------------------------------------------------------------------------- */ + +#define GetFromPC_B movl PC_Reg_E, EffectiveAddr_E; \ + incw PC_Reg; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); + +#define GetFromPC_W movl PC_Reg_E, EffectiveAddr_E; \ + incw EffectiveAddr; \ + addw $2, PC_Reg; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); \ + decw EffectiveAddr; \ + movb %al, %ah; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); \ + +#define GetFromEA_B call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); + +#define GetFromEA_W incw EffectiveAddr; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); \ + decw EffectiveAddr; \ + movb %al, %ah; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); + +#define PutToEA_B call *SN(cpu65_vmem)+4\ + (,EffectiveAddr_E,8); +#define GetFromMem_B(x) \ + movl x, EffectiveAddr_E; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); + +#define GetFromMem_W(x) \ + movl x, EffectiveAddr_E; \ + incw EffectiveAddr; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); \ + decw EffectiveAddr; \ + movb %al, %ah; \ + call *SN(cpu65_vmem) \ + (,EffectiveAddr_E,8); \ + +/* h means hooked */ +#ifdef DEBUGGER +#define GetFromEA_Bh orb $1, SN(cpu65_debug)+3; \ + GetFromEA_B + +#define PutToEA_Bh orb $2, SN(cpu65_debug)+3; \ + orb %al, SN(cpu65_debug)+2; \ + PutToEA_B + +/* reset operation code before each instruction. This assumes %al + * is zero, and is inserted into Continue */ +#define ZeroOp mov %al, SN(cpu65_debug)+3; + +#else /* !DEBUGGER */ +#define GetFromEA_Bh GetFromEA_B +#define PutToEA_Bh PutToEA_B +#define ZeroOp +#endif /* !DEBUGGER */ + + /* The OR actually functions as a move, but we + * want to set the flags and we know %ah is zero */ +#define Continue movl SN(cpu65_delay), %eax; \ + 0: decl %eax; \ + jnz 0b; \ + orb SN(cpu65__signal), %ah; \ + jnz exception; \ + ZeroOp \ + GetFromPC_B \ + jmp *cpu65__opcodes(,%eax,4); + +#define SaveState movw EffectiveAddr, SN(cpu65_debug); \ + movw PC_Reg, SN(cpu65_current); \ + movb A_Reg, SN(cpu65_current)+2; \ + movb F_Reg, SN(cpu65_current)+3; \ + movb X_Reg, SN(cpu65_current)+4; \ + movb Y_Reg, SN(cpu65_current)+5; \ + movb SP_Reg_L, SN(cpu65_current)+6; + +/* The xorls clear the high parts of the registers + * Note: dependent on register assignment + * + * The extra bit at the end points the stack pointer at the alternate + * stack in ALTZP mode. (Note, this is not good -- I'd prefer to avoid + * polluting this module with Apple-specific stuff. But we need to do + * it, else aux-stack using programs will crash when debugged.) + */ +#define ReplaceState xorl %eax, %eax; \ + xorl %ebx, %ebx; \ + xorl %ecx, %ecx; \ + movl $0x0100, %edx; \ + xorl %esi, %esi; \ + xorl %edi, %edi; \ + movw SN(cpu65_debug), EffectiveAddr; \ + movw SN(cpu65_current), PC_Reg; \ + movb SN(cpu65_current)+2, A_Reg; \ + movb SN(cpu65_current)+3, F_Reg; \ + movb SN(cpu65_current)+4, X_Reg; \ + movb SN(cpu65_current)+5, Y_Reg; \ + movb SN(cpu65_current)+6, SP_Reg_L; \ + testl $SS_ALTZP, SN(softswitches); \ + jz 9f; \ + orl $0x10000, %edx; \ +9: + +#define FlagC lahf; \ + andb $C_Flag, %ah; \ + andb $~C_Flag, F_Reg; \ + orb %ah, F_Reg; + +#define FlagZ lahf; \ + andb $Z_Flag, %ah; \ + andb $~Z_Flag, F_Reg; \ + orb %ah, F_Reg; + +#define FlagN lahf; \ + andb $N_Flag, %ah; \ + andb $~N_Flag, F_Reg; \ + orb %ah, F_Reg; + +#define FlagNZ lahf; \ + andb $(N_Flag|Z_Flag), %ah; \ + andb $~(N_Flag|Z_Flag), F_Reg; \ + orb %ah, F_Reg; + +#define FlagNZC lahf; \ + andb $(N_Flag|Z_Flag|C_Flag), %ah; \ + andb $~(N_Flag|Z_Flag|C_Flag), F_Reg; \ + orb %ah, F_Reg; + + /* Have to do things a little differently since + * overflow is not read by the LAHF instruction + * + * Use of long operands wastes two bytes on the AND + * constant, but saves three instruction prefixes. + * This doesn't affect the cycle count. + */ +#define FlagNVZC pushfl; \ + popl %eax; \ + andl $0x08C1,%eax; \ + andb $~(N_Flag|V_Flag|Z_Flag|C_Flag), F_Reg; \ + orb %ah, F_Reg; \ + orb %al, F_Reg; + +#define Push(x) movb x, SN(apple_ii_64k)(,SP_Reg,1); \ + decb SP_Reg_L; + +#define Pop(x) incb SP_Reg_L; \ + movb SN(apple_ii_64k)(,SP_Reg,1), x; + +/* Immediate Addressing - the operand is contained in the second byte of the + instruction. */ +#define GetImm movl PC_Reg_E, EffectiveAddr_E; \ + incw PC_Reg; + +/* Absolute Addressing - the second byte of the instruction is the low + order address, and the third byte is the high order byte. */ +#define GetAbs GetFromPC_W; \ + movl %eax, EffectiveAddr_E; + +/* Zero Page Addressing - the second byte of the instruction is an + address on the zero page */ +#define GetZPage GetFromPC_B; \ + movl %eax, EffectiveAddr_E; + +/* Zero Page Indexed Addressing - The effective address is calculated by + adding the second byte to the contents of the index register. Due + to the zero page addressing nature of this mode, no carry is added + to the high address byte, and the crossing of page boundaries does + not occur. */ +#define GetZPage_X GetFromPC_B; \ + addb X_Reg, %al; \ + movl %eax, EffectiveAddr_E; + +#define GetZPage_Y GetFromPC_B; \ + addb Y_Reg, %al; \ + movl %eax, EffectiveAddr_E; + +/* Absolute Indexed Addressing - The effective address is formed by + adding the contents of X or Y to the address contained in the + second and third bytes of the instruction. */ +#define GetAbs_X GetFromPC_W; \ + addb X_Reg, %al; \ + adcb $0, %ah; \ + movl %eax, EffectiveAddr_E; + +#define GetAbs_Y GetFromPC_W; \ + addb Y_Reg, %al; \ + adcb $0, %ah; \ + movl %eax, EffectiveAddr_E; + +/* Absolute Indirect Addressing - The second and third bytes of the + instruction are the low and high bytes of an address, respectively. + The contents of the fully specified memory location is the + low-order byte of the effective address. The next memory location + contains the high order byte of the effective address. */ +/* (unused at the moment. It applies to JMP, but JMP's addressing is done + * without the macro) + */ +#define GetInd GetFromPC_W; \ + GetFromMem_W(%eax) + +/* Zero Page Indirect Addressing (65c02) - The second byte of the + instruction points to a memory location on page zero containing the + low order byte of the effective address. The next location on page + zero contains the high order byte of the address. */ +#define GetIndZPage GetFromPC_B; \ + incb %al; \ + movl %eax, EffectiveAddr_E; \ + GetFromEA_B; \ + movb %al, %ah; \ + decl EffectiveAddr_E; \ + andl $0xFF, EffectiveAddr_E; \ + GetFromEA_B; \ + movl %eax, EffectiveAddr_E; + +/* Zero Page Indexed Indirect Addressing - The second byte is added to + the contents of the X index register; the carry is discarded. The + result of this addition points to a memory location on page zero + whose contents is the low order byte of the effective address. The + next memory location in page zero contains the high-order byte of + the effective address. Both memory locations specifying the high + and low-order bytes must be in page zero. */ +#define GetIndZPage_X GetFromPC_B; \ + addb X_Reg, %al; \ + incb %al; \ + movl %eax, EffectiveAddr_E; \ + GetFromEA_B; \ + movb %al, %ah; \ + decl EffectiveAddr_E; \ + andl $0xFF, EffectiveAddr_E; \ + GetFromEA_B; \ + movl %eax, EffectiveAddr_E; + +/* Indirect Indexed Addressing - The second byte of the instruction + points to a memory location in page zero. The contents of this + memory location are added to the contents of the Y index register, + the result being the low order byte of the effective address. The + carry from this addition is added to the contents of the next page + zero memory location, the result being the high order byte of the + effective address. */ +#define GetIndZPage_Y GetFromPC_B; \ + incb %al; \ + movl %eax, EffectiveAddr_E; \ + GetFromEA_B; \ + movb %al, %ah; \ + decl EffectiveAddr_E; \ + andl $0xFF, EffectiveAddr_E; \ + GetFromEA_B; \ + addb Y_Reg, %al; \ + adcb $0, %ah; \ + movl %eax, EffectiveAddr_E; + +#define DoADC_b GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + adcb %al, A_Reg; \ + FlagNVZC + +#define DoADC_d GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + adcb A_Reg, %al; \ + daa; \ + movb %al, A_Reg; \ + FlagNVZC + +#define DoAND GetFromEA_Bh \ + andb %al, A_Reg; \ + FlagNZ + +#define DoASL GetFromEA_Bh \ + addb %al, %al; \ + FlagNZC \ + PutToEA_Bh \ + + /* SAR (and the following AND) effectively moves + * bit 6 to Bit 3 while leaving Bit 7 unchanged */ +#define DoBIT GetFromEA_Bh \ + testb %al, A_Reg; \ + lahf; \ + sarb $3, %al; \ + andw $0x4088, %ax; \ + andb $~(N_Flag|V_Flag|Z_Flag), F_Reg; \ + orb %al, F_Reg; \ + orb %ah, F_Reg; + +#define DoCMP GetFromEA_Bh \ + cmpb %al, A_Reg; \ + cmc; \ + FlagNZC + +#define DoCPX GetFromEA_Bh \ + cmpb %al, X_Reg; \ + cmc; \ + FlagNZC + +#define DoCPY GetFromEA_Bh \ + cmpb %al, Y_Reg; \ + cmc; \ + FlagNZC + +#define DoDEC GetFromEA_Bh \ + decb %al; \ + FlagNZ \ + PutToEA_Bh + +#define DoEOR GetFromEA_Bh \ + xorb %al, A_Reg; \ + FlagNZ + +#define DoINC GetFromEA_Bh \ + incb %al; \ + FlagNZ \ + PutToEA_Bh + +#define DoJMP movw EffectiveAddr, PC_Reg; + +#define DoJSR movw PC_Reg, %ax; \ + decw %ax; \ + Push(%ah) \ + Push(%al) \ + movw EffectiveAddr, PC_Reg; + +#define DoLDA GetFromEA_Bh \ + movb %al, A_Reg; \ + orb %al, %al; \ + FlagNZ + +#define DoLDX GetFromEA_Bh \ + movb %al, X_Reg; \ + orb %al, %al; \ + FlagNZ + +#define DoLDY GetFromEA_Bh \ + movb %al, Y_Reg; \ + orb %al, %al; \ + FlagNZ + +#define DoLSR GetFromEA_Bh \ + shrb $1, %al; \ + FlagNZC \ + PutToEA_Bh + +#define DoORA GetFromEA_Bh \ + orb %al, A_Reg; \ + FlagNZ + +#define DoROL GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + adcb %al,%al; \ + FlagNZC \ + PutToEA_Bh + +#define DoROR GetFromEA_Bh \ + movb F_Reg, %ah; \ + rorl $1, %eax; \ + orb %al, %al; \ + btr $31, %eax; \ + FlagNZC \ + PutToEA_Bh + +#define DoSBC_b GetFromEA_Bh \ + notb %al; \ + bt $C_Flag_Bit, FF_Reg; \ + adcb %al, A_Reg; \ + FlagNVZC + +#define DoSBC_d GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + cmc; \ + xchgb A_Reg, %al; \ + sbbb A_Reg, %al; \ + das; \ + movb %al, A_Reg; \ + cmc; \ + FlagNVZC + +#define DoSTA movb A_Reg, %al; \ + PutToEA_Bh + +#define DoSTX movb X_Reg, %al; \ + PutToEA_Bh + +#define DoSTY movb Y_Reg, %al; \ + PutToEA_Bh + +/* ------------------------------------------------------------------------- + 65c02 instructions + ------------------------------------------------------------------------- */ + +#define DoSTZ movb $0x0, %al; \ + PutToEA_Bh + +#define DoTRB GetFromEA_Bh \ + testb A_Reg, %al; \ + FlagZ \ + notb A_Reg; \ + andb A_Reg, %al; \ + notb A_Reg; \ + PutToEA_Bh + +#define DoTSB GetFromEA_Bh \ + testb A_Reg, %al; \ + FlagZ \ + orb A_Reg, %al; \ + PutToEA_Bh + +/* ------------------------------------------------------------------------- + Undocumented 6502 (Illegal instructions) + ------------------------------------------------------------------------- */ + + /* AAX = A AND X -> M */ +#define DoAAX movb A_Reg, %al; \ + andb X_Reg, %al; \ + FlagNZ \ + PutToEA_Bh + + /* AMA = ORA 238, AND M, TAX */ +#define DoAMA orb $238, A_Reg; \ + GetFromEA_Bh \ + andb %al, A_Reg; \ + movb A_Reg, X_Reg; \ + FlagNZ + + /* ANA = AND M, Carry = BIT 7 */ + /* NB: assumes A_Reg = %cl */ +#define DoANA GetFromEA_Bh \ + andb %al, A_Reg; \ + bt $7, %ecx; \ + FlagNZC + + /* ANB = same as ANA */ +#define DoANB DoANA + + /* AXM = (A AND X) - M -> X */ +#define DoAXM GetFromEA_Bh \ + andb A_Reg, X_Reg; \ + notb %al; \ + bt $C_Flag_Bit, FF_Reg; \ + adcb %al, X_Reg; \ + FlagNVZC + + /* AXS = (A AND X) -> S, A AND X AND 17 -> M */ + /* HACK!!!!!!!!!!!!!!! */ +#define DoAXS movb A_Reg, SP_Reg_L; \ + andb X_Reg, SP_Reg_L; \ + movb SP_Reg_L, %al; \ + andb $17, %al; \ + FlagNZ /* \ wasn't here */ \ + PutToEA_Bh + + /* DCP = DEC M, CMP M */ +#define DoDCP GetFromEA_Bh \ + decb %al; \ + PutToEA_Bh \ + negb %al; \ + addb A_Reg, %al; \ + FlagNZC + + /* ISB = INC M, SBC M */ +#define DoISB_b GetFromEA_Bh \ + incb %al; \ + PutToEA_Bh \ + notb %al; \ + bt $C_Flag_Bit, FF_Reg; \ + adcb %al, A_Reg; \ + FlagNVZC + +#define DoISB_d GetFromEA_Bh \ + incb %al; \ + PutToEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + cmc; \ + xchgb A_Reg, %al; \ + sbbb A_Reg, %al; \ + das; \ + movb %al, A_Reg; \ + cmc; \ + FlagNVZC + + /* LAN = ROL M, AND M */ +#define DoLAN GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + adcl %eax, %eax; \ + andb %al, A_Reg; \ + bt $8, %eax; \ + FlagNZC \ + PutToEA_Bh + + /* LAS = LDA M, TAX, TXS */ +#define DoLAS GetFromEA_Bh \ + movb %al, A_Reg; \ + movb %al, X_Reg; \ + movb %al, SP_Reg_L; \ + orb %al, %al; \ + FlagNZ + + /* LAX = LDA M, TAX */ +#define DoLAX GetFromEA_Bh \ + movb %al, A_Reg; \ + movb %al, X_Reg; \ + orb %al, %al; \ + FlagNZ + + + /* LOR = ASL M, ORA M */ +#define DoLOR GetFromEA_Bh \ + addb %al, %al; \ + FlagC \ + PutToEA_Bh \ + orb %al, A_Reg; \ + FlagNZ + + /* RAD = ROR M, ADC M */ +#define DoRAD_b GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + rcrb $1, %al; \ + adcb %al, A_Reg; \ + pushl %eax; \ + FlagNVZC \ + popl %eax; \ + PutToEA_Bh + +#define DoRAD_d GetFromEA_Bh \ + bt $C_Flag_Bit, FF_Reg; \ + rcrb $1, %al; \ + pushfl; \ + PutToEA_Bh \ + popfl; \ + adcb A_Reg, %al; \ + daa; \ + movb %al, A_Reg; \ + FlagNVZC + + /* RAM = AND M, LSR A */ +#define DoRAM GetFromEA_Bh \ + andb %al, A_Reg; \ + shrb $1, A_Reg; \ + FlagNZC + + /* RBM = same as RAM */ +#define DoRBM DoRAM + + /* REO = LSR M, EOR M */ +#define DoREO GetFromEA_Bh \ + shrb $1, %al; \ + xorb %al, A_Reg; \ + FlagNZC \ + PutToEA_Bh \ + + /* DoZBC = same as SBC */ +#define DoZBC_b DoSBC_b +#define DoZBC_d DoSBC_d + + /* TEA = (A AND X AND (OP+2)+1) -> M */ +#define DoTEA pushl EffectiveAddr_E; \ + movw PC_Reg, EffectiveAddr; \ + decw EffectiveAddr; \ + GetFromEA_Bh \ + popl EffectiveAddr_E; \ + incb %al; \ + andb A_Reg, %al; \ + andb X_Reg, %al; \ + FlagNZ \ + PutToEA_Bh + + /* TEX = (X AND (OP+2)+1) -> M */ +#define DoTEX pushl EffectiveAddr_E; \ + movw PC_Reg, EffectiveAddr; \ + decw EffectiveAddr; \ + GetFromEA_Bh \ + popl EffectiveAddr_E; \ + incb %al; \ + andb X_Reg, %al; \ + FlagNZ \ + PutToEA_Bh + + /* TEY = (Y AND 1) -> M */ +#define DoTEY movb Y_Reg, %al; \ + andb $1, %al; \ + FlagNZ \ + PutToEA_Bh + + /* XMA = (X AND M) AND (A OR 238) -> A */ + /* HACK!!!!!!!!!!!!!!! */ +#define DoXMA /* the \ wasn't here before */ \ + GetFromEA_Bh \ + andb X_Reg, %al; \ + orb $238, A_Reg; \ + andb %al, A_Reg; \ + FlagNZ + + + /* ---------------------------------------------------------------------- + 6502 routines and instructions + ---------------------------------------------------------------------- */ + + /* ---------------------------------- + ADC instructions + ---------------------------------- */ + +op_ADC_dec: DoADC_d + Continue + +op_ADC_imm: + GetImm + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_zpage: + GetZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_zpage_x: + GetZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_abs: + GetAbs + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_abs_x: + GetAbs_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_abs_y: + GetAbs_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_ind_x: + GetIndZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + +op_ADC_ind_y: + GetIndZPage_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue + + /* ---------------------------------- + AND instructions + ---------------------------------- */ + +op_AND_imm: + GetImm + DoAND + Continue + +op_AND_zpage: + GetZPage + DoAND + Continue + +op_AND_zpage_x: + GetZPage_X + DoAND + Continue + +op_AND_abs: + GetAbs + DoAND + Continue + +op_AND_abs_x: + GetAbs_X + DoAND + Continue + +op_AND_abs_y: + GetAbs_Y + DoAND + Continue + +op_AND_ind_x: + GetIndZPage_X + DoAND + Continue + +op_AND_ind_y: + GetIndZPage_Y + DoAND + Continue + + /* ---------------------------------- + ASL instructions + ---------------------------------- */ + +op_ASL_acc: + addb A_Reg, A_Reg + FlagNZC + Continue + +op_ASL_zpage: + GetZPage + DoASL + Continue + +op_ASL_zpage_x: + GetZPage_X + DoASL + Continue + +op_ASL_abs: + GetAbs + DoASL + Continue + +op_ASL_abs_x: + GetAbs_X + DoASL + Continue + + /* ---------------------------------- + BCC instruction + ---------------------------------- */ + +op_BCC: + GetFromPC_B + testb $C_Flag, F_Reg + jnz op_BCC_not + cbw + addw %ax, PC_Reg +op_BCC_not: + Continue + + /* ---------------------------------- + BCS instruction + ---------------------------------- */ + +op_BCS: + GetFromPC_B + testb $C_Flag, F_Reg + jz op_BCS_not + cbw + addw %ax, PC_Reg +op_BCS_not: + Continue + + /* ---------------------------------- + BEQ instruction + ---------------------------------- */ + +op_BEQ: + GetFromPC_B + testb $Z_Flag, F_Reg + jz op_BEQ_not + cbw + addw %ax, PC_Reg +op_BEQ_not: + Continue + + /* ---------------------------------- + BIT instructions + ---------------------------------- */ + +op_BIT_zpage: + GetZPage + DoBIT + Continue + +op_BIT_abs: + GetAbs + DoBIT + Continue + + /* ---------------------------------- + BMI instruction + ---------------------------------- */ + +op_BMI: + GetFromPC_B + testb F_Reg, F_Reg /* optimized check of N flag, + * which happens to be sign bit */ + jns op_BMI_not + cbw + addw %ax, PC_Reg +op_BMI_not: + Continue + + /* ---------------------------------- + BNE instruction + ---------------------------------- */ + +op_BNE: + GetFromPC_B + testb $Z_Flag, F_Reg + jnz op_BNE_not + cbw + addw %ax, PC_Reg +op_BNE_not: + Continue + + /* ---------------------------------- + BPL instruction + ---------------------------------- */ + +op_BPL: + GetFromPC_B + testb F_Reg, F_Reg /* optimized check of N flag, + * which happens to be sign bit */ + js op_BPL_not + cbw + addw %ax, PC_Reg +op_BPL_not: + Continue + + /* ---------------------------------- + BRK instruction + ---------------------------------- */ + +op_UNK: /* make undefined opcodes fault */ +op_BRK: + incw PC_Reg + movw PC_Reg, %ax + Push(%ah) + Push(%al) + xorl %eax,%eax + movb F_Reg, %al + orb $I_Flag, F_Reg + movb SN(cpu65_flags_encode)(,%eax,1), %al + Push(%al) + movw $0xFFFE, EffectiveAddr + GetFromEA_W + movw %ax, PC_Reg + Continue + + /* ---------------------------------- + BVC instruction + ---------------------------------- */ + +op_BVC: + GetFromPC_B + testb $V_Flag, F_Reg + jnz op_BVC_not + cbw + addw %ax, PC_Reg +op_BVC_not: + Continue + + /* ---------------------------------- + BVS instruction + ---------------------------------- */ + +op_BVS: + GetFromPC_B + testb $V_Flag, F_Reg + jz op_BVS_not + cbw + addw %ax, PC_Reg +op_BVS_not: + Continue + + /* ---------------------------------- + CLC instruction + ---------------------------------- */ + +op_CLC: + andb $~C_Flag, F_Reg + Continue + + /* ---------------------------------- + CLD instruction + ---------------------------------- */ + +op_CLD: + andb $~D_Flag, F_Reg + Continue + + /* ---------------------------------- + CLI instruction + ---------------------------------- */ + +op_CLI: + andb $~I_Flag, F_Reg + Continue + + /* ---------------------------------- + CLV instruction + ---------------------------------- */ + +op_CLV: + andb $~V_Flag, F_Reg + Continue + + /* ---------------------------------- + CMP instructions + ---------------------------------- */ + +op_CMP_imm: + GetImm + DoCMP + Continue + +op_CMP_zpage: + GetZPage + DoCMP + Continue + +op_CMP_zpage_x: + GetZPage_X + DoCMP + Continue + +op_CMP_abs: + GetAbs + DoCMP + Continue + +op_CMP_abs_x: + GetAbs_X + DoCMP + Continue + +op_CMP_abs_y: + GetAbs_Y + DoCMP + Continue + +op_CMP_ind_x: + GetIndZPage_X + DoCMP + Continue + +op_CMP_ind_y: + GetIndZPage_Y + DoCMP + Continue + + /* ---------------------------------- + CPX instructions + ---------------------------------- */ + +op_CPX_imm: + GetImm + DoCPX + Continue + +op_CPX_zpage: + GetZPage + DoCPX + Continue + +op_CPX_abs: + GetAbs + DoCPX + Continue + + /* ---------------------------------- + CPY instructions + ---------------------------------- */ + +op_CPY_imm: + GetImm + DoCPY + Continue + +op_CPY_zpage: + GetZPage + DoCPY + Continue + +op_CPY_abs: + GetAbs + DoCPY + Continue + + /* ---------------------------------- + DEC instructions + ---------------------------------- */ + +op_DEC_zpage: + GetZPage + DoDEC + Continue + +op_DEC_zpage_x: + GetZPage_X + DoDEC + Continue + +op_DEC_abs: + GetAbs + DoDEC + Continue + +op_DEC_abs_x: + GetAbs_X + DoDEC + Continue + + /* ---------------------------------- + DEX instruction + ---------------------------------- */ + +op_DEX: + decb X_Reg + FlagNZ + Continue + + /* ---------------------------------- + DEY instruction + ---------------------------------- */ + +op_DEY: + decb Y_Reg + FlagNZ + Continue + + /* ---------------------------------- + EOR instructions + ---------------------------------- */ + +op_EOR_imm: + GetImm + DoEOR + Continue + +op_EOR_zpage: + GetZPage + DoEOR + Continue + +op_EOR_zpage_x: + GetZPage_X + DoEOR + Continue + +op_EOR_abs: + GetAbs + DoEOR + Continue + +op_EOR_abs_x: + GetAbs_X + DoEOR + Continue + +op_EOR_abs_y: + GetAbs_Y + DoEOR + Continue + +op_EOR_ind_x: + GetIndZPage_X + DoEOR + Continue + +op_EOR_ind_y: + GetIndZPage_Y + DoEOR + Continue + + /* ---------------------------------- + INC instructions + ---------------------------------- */ + +op_INC_zpage: + GetZPage + DoINC + Continue + +op_INC_zpage_x: + GetZPage_X + DoINC + Continue + +op_INC_abs: + GetAbs + DoINC + Continue + +op_INC_abs_x: + GetAbs_X + DoINC + Continue + + /* ---------------------------------- + INX instruction + ---------------------------------- */ + +op_INX: + incb X_Reg + FlagNZ + Continue + + /* ---------------------------------- + INY instruction + ---------------------------------- */ + +op_INY: + incb Y_Reg + FlagNZ + Continue + + /* ---------------------------------- + JMP instructions + ---------------------------------- */ + +op_JMP_abs: + GetAbs + DoJMP + Continue + +op_JMP_ind: + xorl %eax, %eax + GetFromMem_B(PC_Reg_E) + xchgb %al, %ah + cmpb $0xFF, %ah + je special_case + incw PC_Reg + GetFromMem_B(PC_Reg_E) + xchgb %al, %ah + GetFromMem_W(%eax) + movw %ax, PC_Reg + Continue +special_case: /*?*/ + incw PC_Reg + subw $0x100, PC_Reg + GetFromMem_B(PC_Reg_E) + xchgb %al, %ah + GetFromMem_W(%eax) + movw %ax, PC_Reg + Continue + + /* ---------------------------------- + JSR instruction + ---------------------------------- */ + +op_JSR: + GetAbs + DoJSR + Continue + + /* ---------------------------------- + LDA instructions + ---------------------------------- */ + +op_LDA_imm: + GetImm + DoLDA + Continue + +op_LDA_zpage: + GetZPage + DoLDA + Continue + +op_LDA_zpage_x: + GetZPage_X + DoLDA + Continue + +op_LDA_abs: + GetAbs + DoLDA + Continue + +op_LDA_abs_x: + GetAbs_X + DoLDA + Continue + +op_LDA_abs_y: + GetAbs_Y + DoLDA + Continue + +op_LDA_ind_x: + GetIndZPage_X + DoLDA + Continue + +op_LDA_ind_y: + GetIndZPage_Y + DoLDA + Continue + + /* ---------------------------------- + LDX instructions + ---------------------------------- */ + +op_LDX_imm: + GetImm + DoLDX + Continue + +op_LDX_zpage: + GetZPage + DoLDX + Continue + +op_LDX_zpage_y: + GetZPage_Y + DoLDX + Continue + +op_LDX_abs: + GetAbs + DoLDX + Continue + +op_LDX_abs_y: + GetAbs_Y + DoLDX + Continue + + /* ---------------------------------- + LDY instructions + ---------------------------------- */ + +op_LDY_imm: + GetImm + DoLDY + Continue + +op_LDY_zpage: + GetZPage + DoLDY + Continue + +op_LDY_zpage_x: + GetZPage_X + DoLDY + Continue + +op_LDY_abs: + GetAbs + DoLDY + Continue + +op_LDY_abs_x: + GetAbs_X + DoLDY + Continue + + /* ---------------------------------- + LSR instructions + ---------------------------------- */ + +op_LSR_acc: + shrb $1, A_Reg + FlagNZC + Continue + +op_LSR_zpage: + GetZPage + DoLSR + Continue + +op_LSR_zpage_x: + GetZPage_X + DoLSR + Continue + +op_LSR_abs: + GetAbs + DoLSR + Continue + +op_LSR_abs_x: + GetAbs_X + DoLSR + Continue + + /* ---------------------------------- + NOP instruction + ---------------------------------- */ + +op_NOP: + Continue + + /* ---------------------------------- + ORA instructions + ---------------------------------- */ + +op_ORA_imm: + GetImm + DoORA + Continue + +op_ORA_zpage: + GetZPage + DoORA + Continue + +op_ORA_zpage_x: + GetZPage_X + DoORA + Continue + +op_ORA_abs: + GetAbs + DoORA + Continue + +op_ORA_abs_x: + GetAbs_X + DoORA + Continue + +op_ORA_abs_y: + GetAbs_Y + DoORA + Continue + +op_ORA_ind_x: + GetIndZPage_X + DoORA + Continue + +op_ORA_ind_y: + GetIndZPage_Y + DoORA + Continue + + /* ---------------------------------- + PHA instruction + ---------------------------------- */ + +op_PHA: + Push(A_Reg) + Continue + + /* ---------------------------------- + PHP instruction + ---------------------------------- */ + +op_PHP: + movb F_Reg, %al + movb SN(cpu65_flags_encode)(,%eax,1), %al + Push(%al) + Continue + + /* ---------------------------------- + PLA instruction + ---------------------------------- */ + +op_PLA: + Pop(A_Reg) + orb A_Reg, A_Reg + FlagNZ + Continue + + /* ---------------------------------- + PLP instruction + ---------------------------------- */ + +op_PLP: + xorl %eax, %eax + Pop(%al) + movb SN(cpu65_flags_decode)(,%eax,1), F_Reg + orb $(B_Flag|X_Flag), F_Reg + Continue + + /* ---------------------------------- + ROL instructions + ---------------------------------- */ + +op_ROL_acc: bt $C_Flag_Bit, FF_Reg + adcb A_Reg, A_Reg + FlagNZC + Continue + +op_ROL_zpage: + GetZPage + DoROL + Continue + +op_ROL_zpage_x: + GetZPage_X + DoROL + Continue + +op_ROL_abs: + GetAbs + DoROL + Continue + +op_ROL_abs_x: + GetAbs_X + DoROL + Continue + + /* ---------------------------------- + ROR instructions + ---------------------------------- */ + /* NB: assumes A_Reg = %cl, F_Reg = %ch */ +op_ROR_acc: + rorw $1, %cx /* Roll flags into accum */ + adcb F_Reg, F_Reg /* Roll carry into flags */ + orb A_Reg, A_Reg + FlagNZ /* implied C */ + Continue + +op_ROR_zpage: + GetZPage + DoROR + Continue + +op_ROR_zpage_x: + GetZPage_X + DoROR + Continue + +op_ROR_abs: + GetAbs + DoROR + Continue + +op_ROR_abs_x: + GetAbs_X + DoROR + Continue + + /* ---------------------------------- + RTI instruction + ---------------------------------- */ + +op_RTI: + xorl %eax, %eax + Pop(%al) + movb SN(cpu65_flags_decode)(,%eax,1), F_Reg + orb $(B_Flag|X_Flag), F_Reg + Pop(%al) + Pop(%ah) + movw %ax, PC_Reg + Continue + + /* ---------------------------------- + RTS instruction + ---------------------------------- */ + +op_RTS: + Pop(%al) + Pop(%ah) + incw %ax + movw %ax, PC_Reg + Continue + + /* ---------------------------------- + SBC instructions + ---------------------------------- */ + +op_SBC_dec: + DoSBC_d + Continue + +op_SBC_imm: + GetImm + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_zpage: + GetZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_zpage_x: + GetZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_abs: + GetAbs + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_abs_x: + GetAbs_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_abs_y: + GetAbs_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_ind_x: + GetIndZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + +op_SBC_ind_y: + GetIndZPage_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue + + /* ---------------------------------- + SEC instruction + ---------------------------------- */ + +op_SEC: + orb $C_Flag, F_Reg + Continue + + /* ---------------------------------- + SED instruction + ---------------------------------- */ + +op_SED: + orb $D_Flag, F_Reg + Continue + + /* ---------------------------------- + SEI instruction + ---------------------------------- */ + +op_SEI: + orb $I_Flag, F_Reg + Continue + + /* ---------------------------------- + STA instructions + ---------------------------------- */ + +op_STA_imm: + GetImm + DoSTA + Continue + +op_STA_zpage: + GetZPage + DoSTA + Continue + +op_STA_zpage_x: + GetZPage_X + DoSTA + Continue + +op_STA_abs: + GetAbs + DoSTA + Continue + +op_STA_abs_x: + GetAbs_X + DoSTA + Continue + +op_STA_abs_y: + GetAbs_Y + DoSTA + Continue + +op_STA_ind_x: + GetIndZPage_X + DoSTA + Continue + +op_STA_ind_y: + GetIndZPage_Y + DoSTA + Continue + + /* ---------------------------------- + STX instructions + ---------------------------------- */ + +op_STX_zpage: + GetZPage + DoSTX + Continue + +op_STX_zpage_y: + GetZPage_Y + DoSTX + Continue + +op_STX_abs: + GetAbs + DoSTX + Continue + + /* ---------------------------------- + STY instructions + ---------------------------------- */ + +op_STY_zpage: + GetZPage + DoSTY + Continue + +op_STY_zpage_x: + GetZPage_X + DoSTY + Continue + +op_STY_abs: + GetAbs + DoSTY + Continue + + /* ---------------------------------- + TAX instruction + ---------------------------------- */ + +op_TAX: + movb A_Reg, X_Reg + orb X_Reg, X_Reg + FlagNZ + Continue + + /* ---------------------------------- + TAY instruction + ---------------------------------- */ + +op_TAY: + movb A_Reg, Y_Reg + orb Y_Reg, Y_Reg + FlagNZ + Continue + + /* ---------------------------------- + TSX instruction + ---------------------------------- */ + +op_TSX: + movb SP_Reg_L, X_Reg + orb X_Reg, X_Reg + FlagNZ + Continue + + /* ---------------------------------- + TXA instruction + ---------------------------------- */ + +op_TXA: + movb X_Reg, A_Reg + orb A_Reg, A_Reg + FlagNZ + Continue + + /* ---------------------------------- + TXS instruction + ---------------------------------- */ + +op_TXS: + movb X_Reg, SP_Reg_L + Continue + + /* ---------------------------------- + TYA instruction + ---------------------------------- */ + +op_TYA: + movb Y_Reg, A_Reg + orb A_Reg, A_Reg + FlagNZ + Continue + + + + +#ifdef APPLE_IIE + + /* ---------------------------------------------------------------------- + 65c02 routines and instructions + ---------------------------------------------------------------------- */ + + /* ---------------------------------- + ADC instruction + ---------------------------------- */ + +op_ADC_ind_zpage: # 72 + GetIndZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ADC_dec # Yes, jump to decimal version + DoADC_b + Continue +op_ADC_ind_zpage_dec: + DoADC_d + Continue + + /* ---------------------------------- + AND instruction + ---------------------------------- */ + +op_AND_ind_zpage: # 32 + GetIndZPage + DoAND + Continue + + /* ---------------------------------- + BIT instructions + ---------------------------------- */ + +op_BIT_zpage_x: # 34 + GetIndZPage + DoBIT + Continue + +op_BIT_abs_x: # 3C + GetAbs_X + DoBIT + Continue + + /* BIT immediate is anomalous in that it does not affect the + * N and V flags, unlike in other addressing modes. + */ +op_BIT_imm: # 89 + GetImm + GetFromEA_Bh + testb %al, A_Reg + FlagZ + Continue + + /* ---------------------------------- + BRA instruction + ---------------------------------- */ + +op_BRA: # 80 + GetFromPC_B + cbw + addw %ax, PC_Reg + Continue + + /* ---------------------------------- + CMP instruction + ---------------------------------- */ + +op_CMP_ind_zpage: # D2 + GetIndZPage + DoCMP + Continue + + /* ---------------------------------- + DEA instruction + ---------------------------------- */ + +op_DEA: # 3A + decb A_Reg + FlagNZ + Continue + + /* ---------------------------------- + EOR instruction + ---------------------------------- */ + +op_EOR_ind_zpage: # 52 + GetIndZPage + DoEOR + Continue + + /* ---------------------------------- + INA instruction + ---------------------------------- */ + +op_INA: # 1A + incb A_Reg + FlagNZ + Continue + + /* ---------------------------------- + JMP instructions + ---------------------------------- */ + +op_JMP_ind_65c02: # 6C - different from 6502 + xorl %eax, %eax + GetFromMem_B(PC_Reg_E) + xchgb %al, %ah + incw PC_Reg + GetFromMem_B(PC_Reg_E) + xchgb %al, %ah + GetFromMem_W(%eax) + movw %ax, PC_Reg + Continue + +op_JMP_abs_ind_x: # 7C + GetFromPC_W + movw %ax, EffectiveAddr + movzbl X_Reg, %eax + addw %ax, EffectiveAddr + GetFromMem_W(EffectiveAddr_E) + movw %ax, PC_Reg + Continue + + /* ---------------------------------- + LDA instruction + ---------------------------------- */ + +op_LDA_ind_zpage: # B2 + GetIndZPage + DoLDA + Continue + + /* ---------------------------------- + ORA instruction + ---------------------------------- */ + +op_ORA_ind_zpage: # 12 + GetIndZPage + DoORA + Continue + + /* ---------------------------------- + PHX instruction + ---------------------------------- */ + +op_PHX: # DA + Push(X_Reg) + Continue + + /* ---------------------------------- + PHY instruction + ---------------------------------- */ + +op_PHY: # 5A + Push(Y_Reg) + Continue + + /* ---------------------------------- + PLX instruction + ---------------------------------- */ + +op_PLX: # FA + Pop(X_Reg) + orb X_Reg, X_Reg + FlagNZ + Continue + + /* ---------------------------------- + PLY instruction + ---------------------------------- */ + +op_PLY: # 7A + Pop(Y_Reg) + orb Y_Reg, Y_Reg + FlagNZ + Continue + + /* ---------------------------------- + STA instruction + ---------------------------------- */ + +op_STA_ind_zpage: # 92 + GetIndZPage + DoSTA + Continue + + /* ---------------------------------- + SBC instruction + ---------------------------------- */ + +op_SBC_ind_zpage: # F2 + GetIndZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_SBC_dec # Yes, jump to decimal version + DoSBC_b + Continue +op_SBC_ind_zpage_dec: + DoSBC_d + Continue + + /* ---------------------------------- + STZ instructions + ---------------------------------- */ + +op_STZ_zpage: # 64 + GetZPage + DoSTZ + Continue + +op_STZ_zpage_x: # 74 + GetZPage_X + Continue + +op_STZ_abs: # 9C + GetAbs + DoSTZ + Continue + +op_STZ_abs_x: # 9E + GetAbs_X + DoSTZ + Continue + + /* ---------------------------------- + TRB instructions + ---------------------------------- */ + +op_TRB_abs: # 1C + GetAbs + DoTRB + Continue + +op_TRB_zpage: # 14 + GetZPage + DoTRB + Continue + + /* ---------------------------------- + TSB instructions + ---------------------------------- */ + +op_TSB_abs: # 0C + GetAbs + DoTSB + Continue + +op_TSB_zpage: # 04 + GetZPage + DoTSB + Continue + + + /* ---------------------------------- + ??? instruction - 65c02 + ---------------------------------- */ +op_UNK_65c02: + Continue + +#endif /* APPLE_IIE */ + + /* ---------------------------------------------------------------------- + Undocumented 6502 (Illegal instructions) + ---------------------------------------------------------------------- */ + + /* ---------------------------------- + HANG instruction + ---------------------------------- */ + +op_HANG: + decw PC_Reg + Continue + + /* ---------------------------------- + NOP_2 instruction + ---------------------------------- */ + +op_NOP_2: + incw PC_Reg + Continue + + /* ---------------------------------- + NOP_3 instruction + ---------------------------------- */ + +op_NOP_3: + addw $2, PC_Reg + Continue + + /* ---------------------------------- + AAX instructions + ---------------------------------- */ + +op_AAX_abs: + GetAbs + DoAAX + Continue + +op_AAX_zpage: + GetZPage + DoAAX + Continue + +op_AAX_zpage_y: + GetZPage_Y + DoAAX + Continue + +op_AAX_ind_x: + GetIndZPage_X + DoAAX + Continue + +op_AAX_ind_y: + GetIndZPage_Y + DoAAX + Continue + + /* ---------------------------------- + AMA instruction + ---------------------------------- */ + +op_AMA_imm: + GetImm + DoAMA + Continue + + /* ---------------------------------- + ANA instruction + ---------------------------------- */ + +op_ANA_imm: + GetImm + DoANA + Continue + + /* ---------------------------------- + ANB instruction + ---------------------------------- */ + +op_ANB_imm: + GetImm + DoANB + Continue + + /* ---------------------------------- + AXM instruction + ---------------------------------- */ + +op_AXM_imm: + GetImm + DoAXM + Continue + + /* ---------------------------------- + AXS instruction + ---------------------------------- */ + +op_AXS_abs_y: + GetAbs_Y + DoAXS + Continue + + /* ---------------------------------- + DCP instructions + ---------------------------------- */ + +op_DCP_zpage: + GetZPage + DoDCP + Continue + +op_DCP_zpage_x: + GetZPage_X + DoDCP + Continue + +op_DCP_abs: + GetAbs + DoDCP + Continue + +op_DCP_abs_x: + GetAbs_X + DoDCP + Continue + +op_DCP_abs_y: + GetAbs_Y + DoDCP + Continue + +op_DCP_ind_x: + GetIndZPage_X + DoDCP + Continue + +op_DCP_ind_y: + GetIndZPage_Y + DoDCP + Continue + + /* ---------------------------------- + ISB instructions + ---------------------------------- */ + +op_ISB_dec: + DoISB_d + Continue + +op_ISB_zpage: + GetZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + +op_ISB_zpage_x: + GetZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + + +op_ISB_abs: + GetAbs + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + +op_ISB_abs_x: + GetAbs_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + +op_ISB_abs_y: + GetAbs_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + +op_ISB_ind_x: + GetIndZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + +op_ISB_ind_y: + GetIndZPage_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ISB_dec # Yes, jump to decimal version + DoISB_b + Continue + + /* ---------------------------------- + LAN instructions + ---------------------------------- */ + +op_LAN_zpage: + GetZPage + DoLAN + Continue + +op_LAN_zpage_x: + GetZPage_X + DoLAN + Continue + +op_LAN_abs: + GetAbs + DoLAN + Continue + +op_LAN_abs_x: + GetAbs_X + DoLAN + Continue + +op_LAN_abs_y: + GetAbs_Y + DoLAN + Continue + +op_LAN_ind_x: + GetIndZPage_X + DoLAN + Continue + +op_LAN_ind_y: + GetIndZPage_Y + DoLAN + Continue + + /* ---------------------------------- + LAS instruction + ---------------------------------- */ + +op_LAS_abs_y: + GetAbs_Y + DoLAS + Continue + + /* ---------------------------------- + LAX instructions + ---------------------------------- */ + +op_LAX_zpage: + GetZPage + DoLAX + Continue + +op_LAX_zpage_y: + GetZPage_Y + DoLAX + Continue + +op_LAX_abs: + GetAbs + DoLAX + Continue + +op_LAX_abs_y: + GetAbs_Y + DoLAX + Continue + +op_LAX_ind_x: + GetIndZPage_X + DoLAX + Continue + +op_LAX_ind_y: + GetIndZPage_Y + DoLAX + Continue + + /* ---------------------------------- + LOR instructions + ---------------------------------- */ + +op_LOR_zpage: + GetZPage + DoLOR + Continue + +op_LOR_zpage_x: + GetZPage_X + DoLOR + Continue + +op_LOR_abs: + GetAbs + DoLOR + Continue + +op_LOR_abs_x: + GetAbs_X + DoLOR + Continue + +op_LOR_abs_y: + GetAbs_Y + DoLOR + Continue + +op_LOR_ind_x: + GetIndZPage_X + DoLOR + Continue + +op_LOR_ind_y: + GetIndZPage_Y + DoLOR + Continue + + /* ---------------------------------- + RAD instructions + ---------------------------------- */ + +op_RAD_dec: + DoRAD_d + Continue + +op_RAD_zpage: + GetZPage + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_zpage_x: + GetZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_abs: + GetAbs + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_abs_x: + GetAbs_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_abs_y: + GetAbs_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_ind_x: + GetIndZPage_X + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + +op_RAD_ind_y: + GetIndZPage_Y + testb $D_Flag, F_Reg # Decimal mode? + jnz op_RAD_dec # Yes, jump to decimal version + DoRAD_b + Continue + + /* ---------------------------------- + RAM instruction + ---------------------------------- */ + +op_RAM_imm: + GetImm + DoRAM + Continue + + /* ---------------------------------- + RBM instruction + ---------------------------------- */ + +op_RBM_imm: + GetImm + DoRBM + Continue + + /* ---------------------------------- + REO instructions + ---------------------------------- */ + +op_REO_zpage: + GetZPage + DoREO + Continue + +op_REO_zpage_x: + GetZPage_X + DoREO + Continue + +op_REO_abs: + GetAbs + DoREO + Continue + +op_REO_abs_x: + GetAbs_X + DoREO + Continue + +op_REO_abs_y: + GetAbs_Y + DoREO + Continue + +op_REO_ind_x: + GetIndZPage_X + DoREO + Continue + +op_REO_ind_y: + GetIndZPage_Y + DoREO + Continue + + /* ---------------------------------- + ZBC instruction + ---------------------------------- */ + +op_ZBC_imm: + GetImm + testb $D_Flag, F_Reg # Decimal mode? + jnz op_ZBC_dec # Yes, jump to decimal version + DoZBC_b + Continue +op_ZBC_dec: + DoZBC_d + Continue + + /* ---------------------------------- + TEA instruction + ---------------------------------- */ + +op_TEA_abs_y: + GetAbs_Y + DoTEA + Continue + + /* ---------------------------------- + TEX instruction + ---------------------------------- */ + +op_TEX_abs_y: + GetAbs_Y + DoTEX + Continue + + /* ---------------------------------- + TEY instruction + ---------------------------------- */ + +op_TEY_abs_x: + GetAbs_X + DoTEY + Continue + + /* ---------------------------------- + XMA instruction + ---------------------------------- */ + +op_XMA_imm: + GetImm + DoXMA + Continue + + +/* Exception handler */ + +#ifdef DEBUGGER + +exception: cmpb $RebootSig, %ah + jz ex_reboot + cmpb $ResetSig, %ah + jz ex_reset + cmpb $DebugStepSig, %ah + jz ex_step + jmp ex_enter + +ex_step: SaveState + movb $0, SN(cpu65__signal) + popal + ret + +ex_enter: SaveState + movb $0, SN(cpu65__signal) + pushal + call SN(enter_debugger) + popal + ReplaceState + xorb %ah, %ah + GetFromPC_B + jmp *cpu65__opcodes(,%eax,4) + +ex_reboot: popal + movb $0, SN(cpu65__signal) + ret + +ex_reset: movb $0, SN(cpu65__signal) + movw $0xfffc, EffectiveAddr + GetFromEA_W + movw %ax, PC_Reg + xorb %ah, %ah + GetFromPC_B + jmp *cpu65__opcodes(,%eax,4) + +#else /* !DEBUGGER */ + +exception: cmpb $RebootSig, %ah + jz ex_reboot +ex_reset: movb $0, SN(cpu65__signal) + movw $0xfffc, EffectiveAddr + GetFromEA_W + movw %ax, PC_Reg + xorb %ah, %ah + GetFromPC_B + jmp *cpu65__opcodes(,%eax,4) + +ex_reboot: popal + movb $0, SN(cpu65__signal) + ret; + +#endif /* !DEBUGGER */ + + /* ----------------------------------------------------------------- + * Begin emulation. + * ----------------------------------------------------------------- */ +E(cpu65_run) + pushal + /* Zero all registers, as well as the unused 32-bit parts + * of variables. (which may need to be kept 0) + * + * Note: dependent on assignment of registers */ + xorl %eax, %eax + xorl %ebx, %ebx + xorl %ecx, %ecx + xorl %esi, %esi + xorl %edi, %edi + movl $0x1FF, %edx # Stack pointer + jmp ex_reset + +#ifdef DEBUGGER + +E (cpu65_direct_write) + /* NB: dependent on register choices */ + pushl %edi + movl 8(%esp),%edi + movl 12(%esp),%eax + call * SN(cpu65_vmem)+4(,EffectiveAddr_E,8) + popl %edi + ret + +/* ------------------------------------------------------------------------- + steps the simulation while remaining in the debugger's control + ------------------------------------------------------------------------- */ +E(cpu65_step) + pushal + movb $DebugStepSig,SN(cpu65__signal) + ReplaceState + GetFromPC_B + jmp *cpu65__opcodes(,%eax,4) +#endif + + +/* Tables */ + + .align 4 +E(cpu65__nmosbrk) + .long op_BRK + .long op_ORA_ind_x + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ORA_zpage + .long op_ASL_zpage + .long op_UNK + .long op_PHP + .long op_ORA_imm + .long op_ASL_acc + .long op_UNK + .long op_UNK + .long op_ORA_abs + .long op_ASL_abs + .long op_UNK + .long op_BPL + .long op_ORA_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ORA_zpage_x + .long op_ASL_zpage_x + .long op_UNK + .long op_CLC + .long op_ORA_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ORA_abs_x + .long op_ASL_abs_x + .long op_UNK + .long op_JSR + .long op_AND_ind_x + .long op_UNK + .long op_UNK + .long op_BIT_zpage + .long op_AND_zpage + .long op_ROL_zpage + .long op_UNK + .long op_PLP + .long op_AND_imm + .long op_ROL_acc + .long op_UNK + .long op_BIT_abs + .long op_AND_abs + .long op_ROL_abs + .long op_UNK + .long op_BMI + .long op_AND_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_AND_zpage_x + .long op_ROL_zpage_x + .long op_UNK + .long op_SEC + .long op_AND_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_AND_abs_x + .long op_ROL_abs_x + .long op_UNK + .long op_RTI + .long op_EOR_ind_x + .long op_UNK + .long op_UNK + .long op_UNK + .long op_EOR_zpage + .long op_LSR_zpage + .long op_UNK + .long op_PHA + .long op_EOR_imm + .long op_LSR_acc + .long op_UNK + .long op_JMP_abs + .long op_EOR_abs + .long op_LSR_abs + .long op_UNK + .long op_BVC + .long op_EOR_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_EOR_zpage_x + .long op_LSR_zpage_x + .long op_UNK + .long op_CLI + .long op_EOR_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_EOR_abs_x + .long op_LSR_abs_x + .long op_UNK + .long op_RTS + .long op_ADC_ind_x + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ADC_zpage + .long op_ROR_zpage + .long op_UNK + .long op_PLA + .long op_ADC_imm + .long op_ROR_acc + .long op_UNK + .long op_JMP_ind + .long op_ADC_abs + .long op_ROR_abs + .long op_UNK + .long op_BVS + .long op_ADC_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ADC_zpage_x + .long op_ROR_zpage_x + .long op_UNK + .long op_SEI + .long op_ADC_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_ADC_abs_x + .long op_ROR_abs_x + .long op_UNK + .long op_UNK + .long op_STA_ind_x + .long op_UNK + .long op_UNK + .long op_STY_zpage + .long op_STA_zpage + .long op_STX_zpage + .long op_UNK + .long op_DEY + .long op_UNK + .long op_TXA + .long op_UNK + .long op_STY_abs + .long op_STA_abs + .long op_STX_abs + .long op_UNK + .long op_BCC + .long op_STA_ind_y + .long op_UNK + .long op_UNK + .long op_STY_zpage_x + .long op_STA_zpage_x + .long op_STX_zpage_y + .long op_UNK + .long op_TYA + .long op_STA_abs_y + .long op_TXS + .long op_UNK + .long op_UNK + .long op_STA_abs_x + .long op_UNK + .long op_UNK + .long op_LDY_imm + .long op_LDA_ind_x + .long op_LDX_imm + .long op_UNK + .long op_LDY_zpage + .long op_LDA_zpage + .long op_LDX_zpage + .long op_UNK + .long op_TAY + .long op_LDA_imm + .long op_TAX + .long op_UNK + .long op_LDY_abs + .long op_LDA_abs + .long op_LDX_abs + .long op_UNK + .long op_BCS + .long op_LDA_ind_y + .long op_UNK + .long op_UNK + .long op_LDY_zpage_x + .long op_LDA_zpage_x + .long op_LDX_zpage_y + .long op_UNK + .long op_CLV + .long op_LDA_abs_y + .long op_TSX + .long op_UNK + .long op_LDY_abs_x + .long op_LDA_abs_x + .long op_LDX_abs_y + .long op_UNK + .long op_CPY_imm + .long op_CMP_ind_x + .long op_UNK + .long op_UNK + .long op_CPY_zpage + .long op_CMP_zpage + .long op_DEC_zpage + .long op_UNK + .long op_INY + .long op_CMP_imm + .long op_DEX + .long op_UNK + .long op_CPY_abs + .long op_CMP_abs + .long op_DEC_abs + .long op_UNK + .long op_BNE + .long op_CMP_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_CMP_zpage_x + .long op_DEC_zpage_x + .long op_UNK + .long op_CLD + .long op_CMP_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_CMP_abs_x + .long op_DEC_abs_x + .long op_UNK + .long op_CPX_imm + .long op_SBC_ind_x + .long op_UNK + .long op_UNK + .long op_CPX_zpage + .long op_SBC_zpage + .long op_INC_zpage + .long op_UNK + .long op_INX + .long op_SBC_imm + .long op_NOP + .long op_UNK + .long op_CPX_abs + .long op_SBC_abs + .long op_INC_abs + .long op_UNK + .long op_BEQ + .long op_SBC_ind_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_SBC_zpage_x + .long op_INC_zpage_x + .long op_UNK + .long op_SED + .long op_SBC_abs_y + .long op_UNK + .long op_UNK + .long op_UNK + .long op_SBC_abs_x + .long op_INC_abs_x + .long op_UNK + +#ifdef APPLE_IIE + +E(cpu65__cmos) + .long op_BRK + .long op_ORA_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_TSB_zpage + .long op_ORA_zpage + .long op_ASL_zpage + .long op_UNK_65c02 + .long op_PHP + .long op_ORA_imm + .long op_ASL_acc + .long op_UNK_65c02 + .long op_TSB_abs + .long op_ORA_abs + .long op_ASL_abs + .long op_UNK_65c02 + .long op_BPL + .long op_ORA_ind_y + .long op_ORA_ind_zpage + .long op_UNK_65c02 + .long op_TRB_zpage + .long op_ORA_zpage_x + .long op_ASL_zpage_x + .long op_UNK_65c02 + .long op_CLC + .long op_ORA_abs_y + .long op_INA + .long op_UNK_65c02 + .long op_TRB_abs + .long op_ORA_abs_x + .long op_ASL_abs_x + .long op_UNK_65c02 + .long op_JSR + .long op_AND_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_BIT_zpage + .long op_AND_zpage + .long op_ROL_zpage + .long op_UNK_65c02 + .long op_PLP + .long op_AND_imm + .long op_ROL_acc + .long op_UNK_65c02 + .long op_BIT_abs + .long op_AND_abs + .long op_ROL_abs + .long op_UNK_65c02 + .long op_BMI + .long op_AND_ind_y + .long op_AND_ind_zpage + .long op_UNK_65c02 + .long op_BIT_zpage_x + .long op_AND_zpage_x + .long op_ROL_zpage_x + .long op_UNK_65c02 + .long op_SEC + .long op_AND_abs_y + .long op_DEA + .long op_UNK_65c02 + .long op_BIT_abs_x + .long op_AND_abs_x + .long op_ROL_abs_x + .long op_UNK_65c02 + .long op_RTI + .long op_EOR_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_EOR_zpage + .long op_LSR_zpage + .long op_UNK_65c02 + .long op_PHA + .long op_EOR_imm + .long op_LSR_acc + .long op_UNK_65c02 + .long op_JMP_abs + .long op_EOR_abs + .long op_LSR_abs + .long op_UNK_65c02 + .long op_BVC + .long op_EOR_ind_y + .long op_EOR_ind_zpage + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_EOR_zpage_x + .long op_LSR_zpage_x + .long op_UNK_65c02 + .long op_CLI + .long op_EOR_abs_y + .long op_PHY + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_EOR_abs_x + .long op_LSR_abs_x + .long op_UNK_65c02 + .long op_RTS + .long op_ADC_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_STZ_zpage + .long op_ADC_zpage + .long op_ROR_zpage + .long op_UNK_65c02 + .long op_PLA + .long op_ADC_imm + .long op_ROR_acc + .long op_UNK_65c02 + .long op_JMP_ind_65c02 + .long op_ADC_abs + .long op_ROR_abs + .long op_UNK_65c02 + .long op_BVS + .long op_ADC_ind_y + .long op_ADC_ind_zpage + .long op_UNK_65c02 + .long op_STZ_zpage_x + .long op_ADC_zpage_x + .long op_ROR_zpage_x + .long op_UNK_65c02 + .long op_SEI + .long op_ADC_abs_y + .long op_PLY + .long op_UNK_65c02 + .long op_JMP_abs_ind_x + .long op_ADC_abs_x + .long op_ROR_abs_x + .long op_UNK_65c02 + .long op_BRA + .long op_STA_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_STY_zpage + .long op_STA_zpage + .long op_STX_zpage + .long op_UNK_65c02 + .long op_DEY + .long op_BIT_imm + .long op_TXA + .long op_UNK_65c02 + .long op_STY_abs + .long op_STA_abs + .long op_STX_abs + .long op_UNK_65c02 + .long op_BCC + .long op_STA_ind_y + .long op_STA_ind_zpage + .long op_UNK_65c02 + .long op_STY_zpage_x + .long op_STA_zpage_x + .long op_STX_zpage_y + .long op_UNK_65c02 + .long op_TYA + .long op_STA_abs_y + .long op_TXS + .long op_UNK_65c02 + .long op_STZ_abs + .long op_STA_abs_x + .long op_STZ_abs_x + .long op_UNK_65c02 + .long op_LDY_imm + .long op_LDA_ind_x + .long op_LDX_imm + .long op_UNK_65c02 + .long op_LDY_zpage + .long op_LDA_zpage + .long op_LDX_zpage + .long op_UNK_65c02 + .long op_TAY + .long op_LDA_imm + .long op_TAX + .long op_UNK_65c02 + .long op_LDY_abs + .long op_LDA_abs + .long op_LDX_abs + .long op_UNK_65c02 + .long op_BCS + .long op_LDA_ind_y + .long op_LDA_ind_zpage + .long op_UNK_65c02 + .long op_LDY_zpage_x + .long op_LDA_zpage_x + .long op_LDX_zpage_y + .long op_UNK_65c02 + .long op_CLV + .long op_LDA_abs_y + .long op_TSX + .long op_UNK_65c02 + .long op_LDY_abs_x + .long op_LDA_abs_x + .long op_LDX_abs_y + .long op_UNK_65c02 + .long op_CPY_imm + .long op_CMP_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_CPY_zpage + .long op_CMP_zpage + .long op_DEC_zpage + .long op_UNK_65c02 + .long op_INY + .long op_CMP_imm + .long op_DEX + .long op_UNK_65c02 + .long op_CPY_abs + .long op_CMP_abs + .long op_DEC_abs + .long op_UNK_65c02 + .long op_BNE + .long op_CMP_ind_y + .long op_CMP_ind_zpage + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_CMP_zpage_x + .long op_DEC_zpage_x + .long op_UNK_65c02 + .long op_CLD + .long op_CMP_abs_y + .long op_PHX + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_CMP_abs_x + .long op_DEC_abs_x + .long op_UNK_65c02 + .long op_CPX_imm + .long op_SBC_ind_x + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_CPX_zpage + .long op_SBC_zpage + .long op_INC_zpage + .long op_UNK_65c02 + .long op_INX + .long op_SBC_imm + .long op_NOP + .long op_UNK_65c02 + .long op_CPX_abs + .long op_SBC_abs + .long op_INC_abs + .long op_UNK_65c02 + .long op_BEQ + .long op_SBC_ind_y + .long op_SBC_ind_zpage + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_SBC_zpage_x + .long op_INC_zpage_x + .long op_UNK_65c02 + .long op_SED + .long op_SBC_abs_y + .long op_PLX + .long op_UNK_65c02 + .long op_UNK_65c02 + .long op_SBC_abs_x + .long op_INC_abs_x + .long op_UNK_65c02 + +#endif /* HAVE_IIE */ + +E(cpu65__nmos) + .long op_BRK + .long op_ORA_ind_x + .long op_HANG + .long op_LOR_ind_x + .long op_NOP_2 + .long op_ORA_zpage + .long op_ASL_zpage + .long op_LOR_zpage + .long op_PHP + .long op_ORA_imm + .long op_ASL_acc + .long op_ANA_imm + .long op_NOP_3 + .long op_ORA_abs + .long op_ASL_abs + .long op_LOR_abs + .long op_BPL + .long op_ORA_ind_y + .long op_HANG + .long op_LOR_ind_y + .long op_NOP_2 + .long op_ORA_zpage_x + .long op_ASL_zpage_x + .long op_LOR_zpage_x + .long op_CLC + .long op_ORA_abs_y + .long op_NOP + .long op_LOR_abs_y + .long op_NOP_3 + .long op_ORA_abs_x + .long op_ASL_abs_x + .long op_LOR_abs_x + .long op_JSR + .long op_AND_ind_x + .long op_HANG + .long op_LAN_ind_x + .long op_BIT_zpage + .long op_AND_zpage + .long op_ROL_zpage + .long op_LAN_zpage + .long op_PLP + .long op_AND_imm + .long op_ROL_acc + .long op_ANB_imm + .long op_BIT_abs + .long op_AND_abs + .long op_ROL_abs + .long op_LAN_abs + .long op_BMI + .long op_AND_ind_y + .long op_HANG + .long op_LAN_ind_y + .long op_NOP_2 + .long op_AND_zpage_x + .long op_ROL_zpage_x + .long op_LAN_zpage_x + .long op_SEC + .long op_AND_abs_y + .long op_NOP + .long op_LAN_abs_y + .long op_NOP_3 + .long op_AND_abs_x + .long op_ROL_abs_x + .long op_LAN_abs_x + .long op_RTI + .long op_EOR_ind_x + .long op_HANG + .long op_REO_ind_x + .long op_NOP_2 + .long op_EOR_zpage + .long op_LSR_zpage + .long op_REO_zpage + .long op_PHA + .long op_EOR_imm + .long op_LSR_acc + .long op_RAM_imm + .long op_JMP_abs + .long op_EOR_abs + .long op_LSR_abs + .long op_REO_abs + .long op_BVC + .long op_EOR_ind_y + .long op_HANG + .long op_REO_ind_y + .long op_NOP_2 + .long op_EOR_zpage_x + .long op_LSR_zpage_x + .long op_REO_zpage_x + .long op_CLI + .long op_EOR_abs_y + .long op_NOP + .long op_REO_abs_y + .long op_NOP_3 + .long op_EOR_abs_x + .long op_LSR_abs_x + .long op_REO_abs_x + .long op_RTS + .long op_ADC_ind_x + .long op_HANG + .long op_RAD_ind_x + .long op_NOP_2 + .long op_ADC_zpage + .long op_ROR_zpage + .long op_RAD_zpage + .long op_PLA + .long op_ADC_imm + .long op_ROR_acc + .long op_RBM_imm + .long op_JMP_ind + .long op_ADC_abs + .long op_ROR_abs + .long op_RAD_abs + .long op_BVS + .long op_ADC_ind_y + .long op_HANG + .long op_RAD_ind_y + .long op_NOP_2 + .long op_ADC_zpage_x + .long op_ROR_zpage_x + .long op_RAD_zpage_x + .long op_SEI + .long op_ADC_abs_y + .long op_NOP + .long op_RAD_abs_y + .long op_NOP_3 + .long op_ADC_abs_x + .long op_ROR_abs_x + .long op_RAD_abs_x + .long op_NOP_2 + .long op_STA_ind_x + .long op_NOP_2 + .long op_AAX_ind_x + .long op_STY_zpage + .long op_STA_zpage + .long op_STX_zpage + .long op_AAX_zpage + .long op_DEY + .long op_NOP_2 + .long op_TXA + .long op_XMA_imm + .long op_STY_abs + .long op_STA_abs + .long op_STX_abs + .long op_AAX_abs + .long op_BCC + .long op_STA_ind_y + .long op_HANG + .long op_AAX_ind_y + .long op_STY_zpage_x + .long op_STA_zpage_x + .long op_STX_zpage_y + .long op_AAX_zpage_y + .long op_TYA + .long op_STA_abs_y + .long op_TXS + .long op_AXS_abs_y + .long op_TEY_abs_x + .long op_STA_abs_x + .long op_TEX_abs_y + .long op_TEA_abs_y + .long op_LDY_imm + .long op_LDA_ind_x + .long op_LDX_imm + .long op_LAX_ind_x + .long op_LDY_zpage + .long op_LDA_zpage + .long op_LDX_zpage + .long op_LAX_zpage + .long op_TAY + .long op_LDA_imm + .long op_TAX + .long op_AMA_imm + .long op_LDY_abs + .long op_LDA_abs + .long op_LDX_abs + .long op_LAX_abs + .long op_BCS + .long op_LDA_ind_y + .long op_HANG + .long op_LAX_ind_y + .long op_LDY_zpage_x + .long op_LDA_zpage_x + .long op_LDX_zpage_y + .long op_LAX_zpage_y + .long op_CLV + .long op_LDA_abs_y + .long op_TSX + .long op_LAS_abs_y + .long op_LDY_abs_x + .long op_LDA_abs_x + .long op_LDX_abs_y + .long op_LAX_abs_y + .long op_CPY_imm + .long op_CMP_ind_x + .long op_NOP_2 + .long op_DCP_ind_x + .long op_CPY_zpage + .long op_CMP_zpage + .long op_DEC_zpage + .long op_DCP_zpage + .long op_INY + .long op_CMP_imm + .long op_DEX + .long op_AXM_imm + .long op_CPY_abs + .long op_CMP_abs + .long op_DEC_abs + .long op_DCP_abs + .long op_BNE + .long op_CMP_ind_y + .long op_HANG + .long op_DCP_ind_y + .long op_NOP_2 + .long op_CMP_zpage_x + .long op_DEC_zpage_x + .long op_DCP_zpage_x + .long op_CLD + .long op_CMP_abs_y + .long op_NOP + .long op_DCP_abs_y + .long op_NOP_3 + .long op_CMP_abs_x + .long op_DEC_abs_x + .long op_DCP_abs_x + .long op_CPX_imm + .long op_SBC_ind_x + .long op_NOP_2 + .long op_ISB_ind_x + .long op_CPX_zpage + .long op_SBC_zpage + .long op_INC_zpage + .long op_ISB_zpage + .long op_INX + .long op_SBC_imm + .long op_NOP + .long op_ZBC_imm + .long op_CPX_abs + .long op_SBC_abs + .long op_INC_abs + .long op_ISB_abs + .long op_BEQ + .long op_SBC_ind_y + .long op_HANG + .long op_ISB_ind_y + .long op_NOP_2 + .long op_SBC_zpage_x + .long op_INC_zpage_x + .long op_ISB_zpage_x + .long op_SED + .long op_SBC_abs_y + .long op_NOP + .long op_ISB_abs_y + .long op_NOP_3 + .long op_SBC_abs_x + .long op_INC_abs_x + .long op_ISB_abs_x + diff --git a/src/cpu.h b/src/cpu.h new file mode 100644 index 00000000..e2aef8b0 --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,131 @@ +/* + * Apple // emulator for Linux: Virtual 6502/65C02 interface + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef __ASSEMBLER__ +#include + +/* types */ + +typedef void *WMEM; +typedef void *RMEM; + +struct memory_vector +{ + RMEM r; + WMEM w; +}; + +struct cpu65_state +{ + u_int16_t pc; /* Program counter */ + u_int8_t a; /* Accumulator */ + u_int8_t f; /* Flags (order not same as in real 6502) */ + u_int8_t x,y; /* Index register */ + u_int8_t sp; /* Stack Pointer */ +}; + +struct cpu65_extra /* for debugging */ +{ + u_int16_t ea; /* Last effective address */ + u_int8_t d; /* Last data byte written */ + u_int8_t op; /* 1 = read occured, 2 = write, 3 = both */ +}; + +/* 6502 CPU models */ +#define CPU65_NMOS 0x0 +#define CPU65_C02 0x1 + +#define CPU65_FAULT 0x100 /* Undoc. opcodes are BRK */ +#define CPU65_SYNCHRO 0x200 /* Synchronize speed, not imp. */ + +/* Set up the processor for a new run. Sets up opcode table. + */ +extern void cpu65_set(int flags); + +/* Interrupt the processor */ +extern void cpu65_interrupt(int reason); + +extern void cpu65_run(void); + +extern void cpu65_step(void); + +extern void cpu65_direct_write(int ea,int data); + +extern struct memory_vector cpu65_vmem[65536]; +extern struct cpu65_state cpu65_current; +extern struct cpu65_extra cpu65_debug; + +extern unsigned char cpu65_flags_encode[256]; +extern unsigned char cpu65_flags_decode[256]; + +extern unsigned int cpu65_delay; + +#endif /* !__ASSEMBLER__ */ + +#define RebootSig 0x01 +#define ResetSig 0x02 +#define DebugStepSig 0x04 +#define EnterDebugSig 0x08 + +/* Note: These are *not* the bit positions used for the flags in the P + * register of a real 6502. Rather, they have been distorted so that C, + * N and Z match the analogous flags in the _80386_ flags register. + * + * Additionally, V matches the position of the overflow flag in the high byte + * of the 80386 register. + * + */ +#define C_Flag 0x1 /* 6502 Carry */ +#define X_Flag 0x2 /* 6502 Xtra */ +#define I_Flag 0x4 /* 6502 Interrupt disable */ +#define V_Flag 0x8 /* 6502 Overflow */ +#define B_Flag 0x10 /* 6502 Break */ +#define D_Flag 0x20 /* 6502 Decimal mode */ +#define Z_Flag 0x40 /* 6502 Zero */ +#define N_Flag 0x80 /* 6502 Neg */ + +#define C_Flag_Bit 8 /* 6502 Carry */ +#define X_Flag_Bit 9 /* 6502 Xtra */ +#define I_Flag_Bit 10 /* 6502 Interrupt disable */ +#define V_Flag_Bit 11 /* 6502 Overflow */ +#define B_Flag_Bit 12 /* 6502 Break */ +#define D_Flag_Bit 13 /* 6502 Decimal mode */ +#define Z_Flag_Bit 14 /* 6502 Zero */ +#define N_Flag_Bit 15 /* 6502 Neg */ + +#define X_Reg %bl /* 6502 X register in %bl */ +#define Y_Reg %bh /* 6502 Y register in %bh */ +#define A_Reg %cl /* 6502 A register in %cl */ +#define F_Reg %ch /* 6502 flags in %ch */ +#define FF_Reg %ecx /* 6502 flags for bt */ +#define SP_Reg %edx /* 6502 Stack pointer */ +#define SP_Reg_L %dl /* 6502 Stack pointer low */ +#define SP_Reg_H %dh /* 6502 Stack pointer high */ +#define PC_Reg %si /* 6502 Program Counter */ +#define PC_Reg_E %esi /* 6502 Program Counter */ +#define EffectiveAddr %di /* Effective address */ +#define EffectiveAddr_E %edi /* Effective address */ + +#ifndef __ASSEMBLER__ +/* Private data. */ +extern void *cpu65__opcodes[256]; +extern void *const cpu65__nmos[256]; +extern void *const cpu65__nmosbrk[256]; +extern void *const cpu65__cmos[256]; + +extern unsigned char cpu65__signal; +#endif /* !__ASSEMBLER__ */ + diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 00000000..882496fe --- /dev/null +++ b/src/debug.h @@ -0,0 +1,104 @@ +/* + * Apple // emulator for Linux: Definitions for debugger + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + + +#ifndef A2_DEBUG_H +#define A2_DEBUG_H + +#include + +/* debugger defines */ +#define BUF_X 39 +#define BUF_Y 22 +#define MAX_BRKPTS 16 +#define SCREEN_X 41 +#define SCREEN_Y 24 +#define PROMPT_X 2 +#define PROMPT_Y BUF_Y - 1 +#define PROMPT_END_X BUF_X - 2 +#define command_line command_buf[PROMPT_Y] +#define uchar unsigned char + +/* debugger commands */ +enum token_type { MEM, DIS, REGS, SETMEM, STEP, FINISH, UNTIL, GO, VM, + BREAK, WATCH, CLEAR, IGNORE, STATUS, OPCODES, LC, DRIVE, + SEARCH, HELP, LOG, BSAVE, BLOAD, SAVE, UNKNOWN }; + +enum addressing_mode +{ + addr_implied, + addr_accumulator, + addr_immediate, + addr_zeropage, + addr_zeropage_x, + addr_zeropage_y, + addr_absolute, + addr_absolute_x, + addr_absolute_y, + addr_indirect, + addr_indirect_x, + addr_indirect_y, + addr_j_indirect, /* non-zeropage indirects, used in JMP only */ + addr_j_indirect_x, + addr_relative +}; + +struct opcode_struct +{ + const char *mnemonic; + enum addressing_mode mode; +}; + +extern const struct opcode_struct *opcodes; + +extern int step_next; /* stepping over instructions */ +extern char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */ +extern int num_buffer_lines; /* num lines of output */ +extern int arg1, arg2, arg3; /* command arguments */ +extern int breakpoints[MAX_BRKPTS]; /* memory breakpoints */ +extern int watchpoints[MAX_BRKPTS]; /* memory watchpoints */ + +void clear_debugger_screen(); +void bload(FILE*, char*, int); +void show_misc_info(); +unsigned char get_current_opcode(); +void dump_mem(int, int, int, int, int); +void search_mem(char*, int, int); +void set_mem(int, char*); +void set_lc_mem(int, int, char*); +void disasm(int, int, int, int); +void clear_halt(int*, int); +void set_halt(int*, int); +void show_breakpts(); +void show_regs(); +void display_help(); +void show_lc_info(); +void show_disk_info(); +void c_do_step(int); +int at_haltpt(); +void end_step(); +void set_halt_opcode(unsigned char opcode); +void set_halt_65c02(); +void clear_halt_65c02(); +void clear_halt_opcode(unsigned char opcode); +void show_opcode_breakpts(); + +extern const struct opcode_struct opcodes_6502[256]; +extern const struct opcode_struct opcodes_65c02[256]; +extern const struct opcode_struct opcodes_undoc[256]; +extern const char * const disasm_templates[15]; + +#endif diff --git a/src/debug.l-cpp b/src/debug.l-cpp new file mode 100644 index 00000000..95e03017 --- /dev/null +++ b/src/debug.l-cpp @@ -0,0 +1,901 @@ +/* + * Apple // emulator for Linux: Lexer for debugger + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +/* ASSUMPTIONS: + * flex version 2.5.2 or later + * + * this file is processed in several steps. the Makefile first + * runs it through cpp so that we can eliminate whole rules which + * are unnecessary. the generated file is then run through flex + * to generate the actual c code which is then compiled. + * + */ + +%{ + +/* process includes only the second time we parse this file. */ +#define INC(HASH,STR) HASH ## include STR +INC(#,"misc.h") +INC(#,"interface.h") +INC(#,"debug.h") +INC(#,"disk.h") +INC(#,"video.h") +INC(#,"keys.h") +INC(#,) +INC(#,) +INC(#,) +INC(#,"cpu.h") + + +YY_BUFFER_STATE buffer = 0; + +/* + d{is} {lc1|lc2} {/bank/}{addr} {+}{len} + m{em} {lc1|lc2} {/bank/}{addr} {+}{len} + a{scii} {lc1|lc2} {/bank/}{addr} {+}{len} + r{egs} + {lc1|lc2} : + bload + bsave // + (s{tep} | n{ext}) {len} + f{inish} + u{ntil} + g{o} {addr} + sea{rch} {lc1|lc2} + (b{reak} | w{atch}) {addr} + (b{reak} | w{atch}) {addr} + b{reak} op + (c{lear} | i{gnore}) {num} + c{lear} op + key + sta{tus} + l{ang} + dr{ive} + vm + fr{esh} + (? | h{elp}) +*/ + +%} + + +DEC [0-9] +HEX [0-9a-fA-F] +WS [\n\r\t" "] +CHAR [^\n\r\t" "] +BOS ^ +EOS {WS}*\0 +BANK \/0?[01]\/ +ADDRS [0-9a-fA-F]+ + + +%% + + + +{BOS}(me?m?|as?c?i?i?){WS}+{ADDRS}{WS}\+?+{HEX}+{EOS} { + /* mem */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + dump_mem(arg1, arg2, 0, do_ascii, -1); + return MEM; +} + +#ifdef APPLE_IIE +{BOS}(me?m?|as?c?i?i?){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* mem // */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + dump_mem(arg1, arg2, 0, do_ascii, arg3); + return MEM; +} +#endif + +{BOS}(me?m?|as?c?i?i?){WS}+{ADDRS}{EOS} { + /* mem */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + dump_mem(arg1, 256, 0, do_ascii, -1); + return MEM; +} + +#ifdef APPLE_IIE +{BOS}(me?m?|as?c?i?i?){WS}+{BANK}{ADDRS}{EOS} { + /* mem // */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + dump_mem(arg1, 256, 0, do_ascii, arg3); + return MEM; +} +#endif + +{BOS}(me?m?|as?c?i?i?){WS}+\+{HEX}+{EOS} { + /* mem + */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (*debugtext != '+') ++debugtext; + ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + dump_mem(cpu65_current.pc, arg1, 0, do_ascii, -1); + return MEM; +} + +{BOS}(me?m?|as?c?i?i?){EOS} { + /* dump mem from current location */ + int do_ascii = 0; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + dump_mem(cpu65_current.pc, 256, 0, do_ascii, -1); + return MEM; +} + +{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* dump mem from lc */ + int do_ascii = 0; + int lc; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + + lc = strtol(debugtext, &debugtext, 10); + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + dump_mem(arg1, arg2, lc, do_ascii, -1); + return MEM; +} + +#ifdef APPLE_IIE +{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* dump mem from lc // */ + int do_ascii = 0; + int lc; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + dump_mem(arg1, arg2, lc, do_ascii, arg3); + return MEM; +} +#endif + +{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{ADDRS}{EOS} { + /* dump mem from lc */ + int do_ascii = 0; + int lc; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + + lc = strtol(debugtext, &debugtext, 10); + arg1 = strtol(debugtext, &debugtext, 16); + + dump_mem(arg1, 256, lc, do_ascii, -1); + return MEM; +} + +#ifdef APPLE_IIE +{BOS}(me?m?|as?c?i?i?){WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{EOS} { + /* dump mem from lc // */ + int do_ascii = 0; + int lc; + + if (tolower(debugtext[0]) == 'a') + do_ascii = 1; + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + arg1 = strtol(debugtext, &debugtext, 16); + + dump_mem(arg1, 256, lc, do_ascii, arg3); + return MEM; +} +#endif + +{BOS}di?s?{WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* disassemble at */ + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, arg2, 0, -1); + return DIS; +} + +#ifdef APPLE_IIE +{BOS}di?s?{WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* disassemble at // */ + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, arg2, 0, arg3); + return DIS; +} +#endif + +{BOS}di?s?{WS}+{ADDRS}{EOS} { + /* disassemble at */ + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = 256; + if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_current.pc; + + disasm(arg1, arg2, 0, -1); + return DIS; +} + +#ifdef APPLE_IIE +{BOS}di?s?{WS}+{BANK}{ADDRS}{EOS} { + /* disassemble at // */ + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = 256; + if ((arg1 < 0) || (arg1 > 65535)) arg1 = cpu65_current.pc; + + disasm(arg1, arg2, 0, arg3); + return DIS; +} +#endif + +{BOS}di?s?{WS}+\+{HEX}+{EOS} { + /* disassemble current location + */ + while (*debugtext != '+') ++debugtext; + ++debugtext; + + arg1 = strtol(debugtext, &debugtext, 16); + disasm(cpu65_current.pc, arg1, 0, -1); + return DIS; +} + +{BOS}di?s?{EOS} { + /* disassemble current location */ + disasm(cpu65_current.pc, 256, 0, -1); + return DIS; +} + +{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* disassemble language */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + + lc = strtol(debugtext, &debugtext, 10); + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, arg2, lc, -1); + return DIS; +} + +#ifdef APPLE_IIE +{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{WS}+\+?{HEX}+{EOS} { + /* disassemble language // */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + arg2 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, arg2, lc, arg3); + return DIS; +} +#endif + +{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{ADDRS}{EOS} { + /* disassemble language */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + + lc = strtol(debugtext, &debugtext, 10); + arg1 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, 256, lc, -1); + return DIS; +} + +#ifdef APPLE_IIE +{BOS}di?s?{WS}*(lc?1|lc?2){WS}+{BANK}{ADDRS}{EOS} { + /* disassemble language // */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + + arg1 = strtol(debugtext, &debugtext, 16); + + disasm(arg1, 256, lc, arg3); + return DIS; +} +#endif + +{BOS}re?g?s?{EOS} { + /* show cpu state */ + show_regs(); + return REGS; +} + +{BOS}{ADDRS}{WS}*\:{WS}*{HEX}+{EOS} { + /* set memory : */ + arg1 = strtol(debugtext, &debugtext, 16); + + while (*debugtext != ':') ++debugtext; ++debugtext; + while (isspace(*debugtext)) ++debugtext; + + set_mem(arg1, debugtext); + return SETMEM; +} + +{BOS}{ADDRS}{WS}*(lc1|lc2)\:{WS}*{HEX}+{EOS} { + /* set LC memory lc1|lc2 : */ + int lc; + + arg1 = strtol(debugtext, &debugtext, 16); + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + ++debugtext; while (isspace(*debugtext)) ++debugtext; + + set_lc_mem(arg1, lc, debugtext); + return SETMEM; +} + +{BOS}bload{WS}+{CHAR}+{WS}+{ADDRS}{EOS} { + /* bload */ + FILE *fp = NULL; + char *ptr = NULL; + char name[128]; + int len = -1; + + while (!isspace(*debugtext)) ++debugtext; + while (isspace(*debugtext)) ++debugtext; + ptr = debugtext; + while (!isspace(*debugtext)) ++debugtext; + len = debugtext-ptr; + + /* filename */ + strncpy(name, ptr, len); + name[len] = '\0'; + + /* bload addr */ + while (isspace(*debugtext)) ++debugtext; + arg1 = strtol(debugtext, (char**)NULL, 16); + + fp = fopen(name, "r"); + if (fp == NULL) { + sprintf(second_buf[num_buffer_lines++], "problem: %s", name); + perror(name); + return BLOAD; + } + + bload(fp, name, arg1); + fclose(fp); + return BLOAD; +} + +{BOS}(st?e?p?|ne?x?t?){EOS} { + /* step / step next instruction */ + if (*debugtext == 'n') step_next = 1; + + c_do_step(1); + return STEP; +} + +{BOS}(st?e?p?|ne?x?t?){WS}+{HEX}+{EOS} { + /* step / step next instructions */ + if (*debugtext == 'n') step_next = 1; + + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, (char**)NULL, 16); + if ((arg1 < 1) || (arg1 > 255)) arg1 = 255; + + c_do_step(arg1); + return STEP; +} + +{BOS}fi?n?i?s?h?{EOS} { + int step_frame = 1; + unsigned char op; + + /* step until finished with curent stack frame */ + while ((c_mygetch(0) == -1) && !at_haltpt()) { + op = get_current_opcode(); + + if (op == 0x20) ++step_frame; /* JSR */ + if (op == 0x60) --step_frame; /* RTS */ + + if (!step_frame) break; /* finished */ + cpu65_step(); + } + end_step(); /* print location */ + return FINISH; +} + +{BOS}un?t?i?l?{EOS} { + /* step until PC == next instruction. good for finishing backward + loops */ + unsigned char op; + int delta; + op = get_current_opcode(); + + switch (opcodes[op].mode) + { + case addr_implied: + case addr_accumulator: + delta = 1; + break; + case addr_immediate: + case addr_zeropage: + case addr_zeropage_x: + case addr_zeropage_y: + case addr_indirect: + case addr_indirect_x: + case addr_indirect_y: + case addr_relative: + delta = 2; + break; + case addr_absolute: + case addr_absolute_x: + case addr_absolute_y: + case addr_j_indirect: + case addr_j_indirect_x: + delta = 3; + break; + } + + arg1 = cpu65_current.pc + delta; + + while ((cpu65_current.pc != arg1) && !at_haltpt() && (c_mygetch(0) == -1)) + cpu65_step(); + end_step(); /* print location */ + return UNTIL; +} + +{BOS}go?{WS}+{HEX}+{EOS} { + /* jump to addrs and run while remaining in debugger console */ + while (!isspace(*debugtext)) ++debugtext; + + /* DANGEROUS! */ + cpu65_current.pc = strtol(debugtext, (char**)NULL, 16); + while (!at_haltpt() && (c_mygetch(0) == -1)) + cpu65_step(); + end_step(); /* print location */ + return GO; +} + +{BOS}go?{EOS} { + /* run while remaining in debugger console */ + while (!at_haltpt() && (c_mygetch(0) == -1)) + cpu65_step(); + end_step(); /* print location */ + return GO; +} + +{BOS}wa?t?c?h?{EOS} { + /* set watchpoint */ + set_halt(watchpoints, cpu65_current.pc); + return WATCH; +} + +{BOS}wa?t?c?h?{WS}+{HEX}+{EOS} { + /* set watchpoint */ + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, (char**)NULL, 16); + if ((arg1 < 0) || (arg1 > 65535)) { + sprintf(second_buf[num_buffer_lines++], "invalid address"); + return WATCH; + } + + set_halt(watchpoints, arg1); + return WATCH; +} + + +{BOS}br?e?a?k?{EOS} { + /* set breakpoint */ + set_halt(breakpoints, cpu65_current.pc); + return BREAK; +} + +{BOS}br?e?a?k?{WS}+{HEX}+{EOS} { + /* set breakpoint */ + while (!isspace(*debugtext)) ++debugtext; + + arg1 = strtol(debugtext, (char**)NULL, 16); + if ((arg1 < 0) || (arg1 > 65535)) { + sprintf(second_buf[num_buffer_lines++], "invalid address"); + return BREAK; + } + + set_halt(breakpoints, arg1); + return BREAK; +} + +{BOS}br?e?a?k?{WS}*op{WS}+{HEX}+{EOS} { + /* set breakpoint */ + while (!(*debugtext == 'p')) ++debugtext; + ++debugtext; + + arg1 = strtol(debugtext, (char**)NULL, 16); + if ((arg1 < 0) || (arg1 > 0xFF)) { + sprintf(second_buf[num_buffer_lines++], "invalid opcode"); + return BREAK; + } + + set_halt_opcode((unsigned char)arg1); + return BREAK; +} + +#ifdef APPLE_IIE +{BOS}br65c02{EOS} { + /* set opcode breakpoints on 65c02 instructions */ + set_halt_65c02(); + return BREAK; +} +#endif + +{BOS}ig?n?o?r?e?{EOS} { + /* ignore everything */ + clear_halt(watchpoints, 0); + sprintf(second_buf[num_buffer_lines++], "ignored all"); + return IGNORE; +} + +{BOS}ig?n?o?r?e?({WS}+{DEC}+)+{EOS} { + /* ignore ... */ + + while (!isspace(*debugtext)) ++debugtext; + + while (*debugtext) { + arg1 = strtol(debugtext, &debugtext, 10); + if ((arg1 < 1) || (arg1 > MAX_BRKPTS)) { + sprintf(second_buf[num_buffer_lines++], "invalid watchpoint"); + return IGNORE; + } + clear_halt(watchpoints, arg1); + sprintf(second_buf[num_buffer_lines++], "ignored %d", arg1); + } + return IGNORE; +} + + +{BOS}cl?e?a?r?{EOS} { + /* clear everything */ + clear_halt(breakpoints, 0); + sprintf(second_buf[num_buffer_lines++], "cleared all"); + return CLEAR; +} + +{BOS}cl?e?a?r?({WS}+{DEC}+)+{EOS} { + /* clear ... */ + while (!isspace(*debugtext)) ++debugtext; + + while (*debugtext) { + arg1 = strtol(debugtext, &debugtext, 10); + if ((arg1 < 1) || (arg1 > MAX_BRKPTS)) { + sprintf(second_buf[num_buffer_lines++], "invalid breakpoint"); + return CLEAR; + } + clear_halt(breakpoints, arg1); + sprintf(second_buf[num_buffer_lines++], "cleared %d", arg1); + } + return CLEAR; +} + +{BOS}cl?e?a?r?{WS}*op({WS}+{HEX}+)+{EOS} { + /* clear ... */ + while (!(*debugtext == 'p')) ++debugtext; + ++debugtext; + + while (*debugtext) { + arg1 = strtol(debugtext, &debugtext, 16); + if ((arg1 < 0) || (arg1 > 255)) { + sprintf(second_buf[num_buffer_lines++], "invalid opcode"); + return CLEAR; + } + clear_halt_opcode((unsigned char)arg1); + sprintf(second_buf[num_buffer_lines++], "cleared opcode %02X", + (unsigned char)arg1); + } + return CLEAR; +} + +#ifdef APPLE_IIE +{BOS}cl65c02{EOS} { + /* clear 65c02 ... */ + clear_halt_65c02(); + return CLEAR; +} +#endif + +{BOS}stat?u?s?{EOS} { + /* show breakpoints and watchpoints */ + show_breakpts(); + return STATUS; +} + +{BOS}opc?o?d?e?s?{EOS} { + /* show opcode breakpoints */ + show_opcode_breakpts(); + return OPCODES; +} + +{BOS}sea?r?c?h?{WS}+{HEX}+{EOS} { + /* search main memory for */ + while (!isspace(*debugtext)) ++debugtext; + while (isspace(*debugtext)) ++debugtext; + + search_mem(debugtext, 0, -1); + + return SEARCH; +} + +#ifdef APPLE_IIE +{BOS}sea?r?c?h?{WS}+{BANK}{WS}+{HEX}+{EOS} { + /* search memory for */ + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + while (isspace(*debugtext)) ++debugtext; + + search_mem(debugtext, 0, arg3); + + return SEARCH; +} +#endif + +{BOS}sea?r?c?h?{WS}*(lc?1|lc?2){WS}+{HEX}+{EOS} { + /* search LC for */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (!isspace(*debugtext)) ++debugtext; + while (isspace(*debugtext)) ++debugtext; + + search_mem(debugtext, lc, -1); + + return SEARCH; +} + +#ifdef APPLE_IIE +{BOS}sea?r?c?h?{WS}*(lc?1|lc?2){WS}+{BANK}{WS}+{HEX}+{EOS} { + /* search LC memory for */ + int lc; + + while (tolower(*debugtext) != 'l') ++debugtext; ++debugtext; + if (tolower(*debugtext) == 'c') ++debugtext; + lc = strtol(debugtext, &debugtext, 10); + + while (*debugtext != '/') ++debugtext; + ++debugtext; /* after / */ + arg3 = strtol(debugtext, &debugtext, 10); + ++debugtext; /* after / */ + while (isspace(*debugtext)) ++debugtext; + + search_mem(debugtext, lc, arg3); + + return SEARCH; +} +#endif + +{BOS}key{WS}+{HEX}+{EOS} { + /* send key code to emulator */ + unsigned char key; + + while (!isspace(*debugtext)) ++debugtext; + while (isspace(*debugtext)) ++debugtext; + key = (unsigned char) strtol(debugtext, &debugtext, 16); + + apple_ii_64k[0][0xC000] = key; + apple_ii_64k[1][0xC000] = key; +} + +{BOS}la?n?g?{EOS} { + /* display language card settings */ + show_lc_info(); + return LC; +} + +{BOS}dri?v?e?{EOS} { + /* show disk settings */ + show_disk_info(); + return DRIVE; +} + +{BOS}vm?{EOS} { + /* show other VM softswitch settings */ + show_misc_info(); + return VM; +} + +{BOS}fre?s?h?{EOS} { + /* refresh the screen */ + clear_debugger_screen(); +} + +{BOS}(\?|he?l?p?){EOS} { + display_help(); + return HELP; +} + +{BOS}bsave{WS}+{CHAR}+{WS}+{BANK}{ADDRS}{WS}+{HEX}+{EOS} { + /* bsave // */ + /* save memory dump to file */ + FILE *fp = NULL; + char *ptr = NULL; + int len, start, len2, bank; + + while (!isspace(*debugtext)) ++debugtext; + while (isspace(*debugtext)) ++debugtext; + + /* copy file name */ + ptr = debugtext; + while (!isspace(*debugtext)) ++debugtext; + len = debugtext - ptr; + strncpy(temp, ptr, len); + temp[len] = '\0'; + + /* get bank info */ + while (*debugtext != '/') ++debugtext; + ++debugtext; + bank = strtol(debugtext, &debugtext, 10); + ++debugtext; + + /* extract start and len */ + start = strtol(debugtext, &debugtext, 16); + len2 = strtol(debugtext, &debugtext, 16); + + fp = fopen(temp, "w"); /* try to open file for writing */ + if (fp == NULL) { + sprintf(second_buf[num_buffer_lines++], "problem: %s", temp); + perror(temp); + return BSAVE; + } + len = fwrite(apple_ii_64k[bank]+start, 1, len2, fp); + if (len < len2) { + sprintf(second_buf[num_buffer_lines++], "problem: %s", temp); + perror(temp); + fclose(fp); + return BSAVE; + } + + sprintf(second_buf[num_buffer_lines++], "bsaved: %s", temp); + fclose(fp); + return BSAVE; +} + +{BOS}log{EOS} { + /* log debugger output to file - not implemented */ + return LOG; +} + +{BOS}save{EOS} { + /* save apple2 state to a .img file - not implemented I'd like to + * be compatible with the applePC emulator's .img format. anyone + * have documentation on this? -ASC + **/ + return SAVE; +} + + +\n /* ignore newlines */ + +. /* ignore extraneous characters */ + + +%% + + +int yywrap () { + return 1; +} + +/* initialize the buffer - needed each time through */ +void init_lex (char *str, int size) { + if (buffer) yy_delete_buffer(buffer); + buffer = yy_scan_buffer(str, size); + + if (!buffer) { /* oops */ + video_shutdown(); + printf("lex buffer not big enough\n"); + exit(1); + } +} diff --git a/src/debugger.c b/src/debugger.c new file mode 100644 index 00000000..535b699c --- /dev/null +++ b/src/debugger.c @@ -0,0 +1,1135 @@ +/* + * Apple // emulator for Linux: Main debugger routines + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifdef DEBUGGER +#include "debug.h" +#include "misc.h" +#include "keys.h" +#include "video.h" +#include "disk.h" +#include "interface.h" +#include "cpu.h" +#include "prefs.h" + +#include +#include +#include +#include + +const struct opcode_struct *opcodes; + +int step_next; /* stepping over instructions */ +char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */ +int num_buffer_lines; /* num lines of output */ +int arg1, arg2, arg3; /* command arguments */ +int breakpoints[MAX_BRKPTS]; /* memory breakpoints */ +int watchpoints[MAX_BRKPTS]; /* memory watchpoints */ + +/* debugger globals */ +static unsigned char screen[SCREEN_Y][SCREEN_X] = + { "||||||||||||||||||||||||||||||||||||||||", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "||||||||||||||||||||||||||||||||||||||||" }; + +static char command_buf[BUF_Y][BUF_X]; /* command line prompt */ +char lexbuf[BUF_X+2]; /* comman line to be flex'ed */ + +unsigned char current_opcode; + +int op_breakpoints[256]; /* opcode breakpoints */ + +/* in debug.l */ +extern int debuglex(); /* yylex() */ +extern void init_lex(char *buf, int size); + +/* ------------------------------------------------------------------------- + c_get_current_rambank (addrs) - return the current ram bank for addrs. + returns 0 = bank 0 + 1 = bank 1 + ------------------------------------------------------------------------- */ +int c_get_current_rambank(int addrs) { +#ifdef APPLE_IIE + if ((addrs >= 0x200) && (addrs < 0xD000)) { + + + /* SLOTROM */ + if ((addrs >= 0xC100) && (addrs < 0xD000)) { + /* expansion rom */ + if ((addrs >= 0xC800) && (addrs < 0xD000)) + return 1; /* always internal + * (the real rules are more complex, but + * this'll suffice since the slot 3 pseudo-card + * is the only one with c8 space) */ + + /* if SLOTCXROM, then internal rom (regardless of + SLOTC3ROM setting). */ + if (softswitches & SS_CXROM) + return 1; + + /* slot 3 rom */ + if ((addrs >= 0xC300) && (addrs < 0xC400)) { + return !!(softswitches & SS_C3ROM); + } + + return 0; /* peripheral rom */ + } + + /* text page 1 */ + if ((addrs >= 0x400) && (addrs < 0x800)) + { + return !!(softswitches & SS_TEXTRD); + } + + /* hires page 1 with 80STORE and HIRES on */ + if ((addrs >= 0x2000) && (addrs < 0x4000)) + { + return !!(softswitches & SS_HGRRD); + } + + /* otherwise return RAMRD flag */ + return !!(softswitches & SS_RAMRD); + } + + /* executing in ALTZP space. */ + return !!(softswitches & SS_ALTZP); + +#else + return 0; +#endif +} + +/* ------------------------------------------------------------------------- + get_current_opcode () - returns the opcode from the address that + the PC is currently reading from. + returns 0 = bank 0 + 1 = bank 1 + ------------------------------------------------------------------------- */ +unsigned char get_current_opcode() { + int bank = c_get_current_rambank(cpu65_current.pc); + int lcbank = 0; + + /* main RAM */ + if (cpu65_current.pc < 0xD000) { + return apple_ii_64k[bank][cpu65_current.pc]; + } + + /* LC RAM */ + if (cpu65_current.pc >= 0xE000) { + if (softswitches & SS_LCRAM) + return language_card[bank][cpu65_current.pc-0xE000]; + else + return apple_ii_64k[bank][cpu65_current.pc]; + } + + /* LC BANK RAM */ + if (softswitches & SS_BANK2) + lcbank = 0x1000; + + if (softswitches & SS_LCRAM) + return language_banks[bank][cpu65_current.pc-0xD000+lcbank]; + else + return apple_ii_64k[bank][cpu65_current.pc]; +} + +/* ------------------------------------------------------------------------- + dump_mem () - hexdump of memory to debug console + we DO NOT wrap the display : 0xffff -> 0x0 (programs can't wrap) + ------------------------------------------------------------------------- */ + +void dump_mem(int addrs, int len, int lc, int do_ascii, int rambank) { + int i, j, mod, end; + unsigned char op; + int orig_addrs = addrs; /* address for display */ + + /* check which rambank */ + if (rambank == -1) { + rambank = c_get_current_rambank(addrs); + } + + if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000)) + /* read lc anyway */ + lc = 1 + !!(softswitches & SS_BANK2); + + if ((addrs < 0) || (addrs > 0xffff)) { + addrs = cpu65_current.pc; + orig_addrs = addrs; + } + if (lc) { + orig_addrs = addrs; + if ((addrs >= 0xd000) && (addrs <= 0xffff)) addrs -= 0xd000; + if ((addrs < 0) || (addrs > 0x2fff)) addrs = 0; + } + + if ((len < 1) || (len > 256)) len = 256; + if (do_ascii && (len > 128)) len = 128; + + + /* save hexdump in second_buf */ + end = (lc) ? 0x3000 : 0x10000; + for (i = num_buffer_lines-1, j = 0; ((j < len) && (addrs+j < end)); j++) { + + mod = j % (16 >> do_ascii); + + if (lc) { + op = (addrs+j >= 0x1000) ? language_card[rambank][(addrs+j)-0x1000] + : (lc == 1) ? language_banks[rambank][addrs+j] + : language_banks[rambank][0x1000+addrs+j] ; + } + else op = apple_ii_64k[rambank][addrs+j]; + + if (!mod) { + if (++i) { + for (mod=0; mod 31) ? (op&0x7f) : '.'); + continue; + } + sprintf(second_buf[i]+5+mod*2, "%02X", op); + if (do_ascii) sprintf(second_buf[i]+23+mod, "%c", + ((op&0x7f) > 31) ? (op&0x7f) : '.'); + } + for (mod=0; mod= 0x1000) ? language_card[rambank][i-0x1000] + : (lc == 1) ? language_banks[rambank][i] + : language_banks[rambank][0x1000+i] ; + } + else op = apple_ii_64k[rambank][i]; + + if (byte == op) { /* matched byte? */ + ++j; /* increment */ + if (!isxdigit(*(hexstr+j))) { /* end of bytes? */ + /* then we found a match */ + sprintf(second_buf[num_buffer_lines], "%04X: %s", + i-(j>>1), hexstr); + num_buffer_lines = (num_buffer_lines + 1) % (BUF_Y-2); + j = 0; continue; + } + ++j; + if (!isxdigit(*(hexstr+j))) { /* end of bytes? */ + /* then we found a match */ + sprintf(second_buf[num_buffer_lines], "%04X: %s", + i-(j>>1)+1, hexstr); + num_buffer_lines = (num_buffer_lines + 1) % (BUF_Y-2); + j = 0; continue; + } + continue; + } + j = 0; + } +} + + +/* ------------------------------------------------------------------------- + set_mem () - write to memory. we use the do_write_memory routine + to "safely" set memory... + ------------------------------------------------------------------------- */ +void set_mem(int addrs, char *hexstr) { + static char scratch[3]; + unsigned char data; + + if ((addrs < 0) || (addrs > 0xffff)) { + sprintf(second_buf[num_buffer_lines++], "invalid address"); + return; + } + + while (*hexstr) { + strncpy(scratch, hexstr, 2); + data = (unsigned char) strtol(scratch, (char**)NULL, 16); + + /* call the set_memory routine, which knows how to route the + request */ + cpu65_direct_write(addrs,data); + + ++hexstr; + if (!*hexstr) break; + ++hexstr; + if (++addrs > 0xffff) return; /* don't overwrite memory */ + } +} + + +/* ------------------------------------------------------------------------- + set_lc_mem () - specifically write to apple II language card RAM memory + ------------------------------------------------------------------------- */ +void set_lc_mem(int addrs, int lcbank, char *hexstr) { + static char scratch[3]; + unsigned char data; + + if ((addrs >= 0xd000) && (addrs <= 0xffff)) addrs -= 0xd000; + if ((addrs < 0) || (addrs > 0x2fff)) { + sprintf(second_buf[num_buffer_lines++], "invalid LC address"); + return; + } + + while (*hexstr) { + strncpy(scratch, hexstr, 2); + data = (unsigned char) strtol(scratch, (char**)NULL, 16); + + /* ??? no way to write to aux LC banks */ + + if (addrs >= 0x1000) + language_card[0][addrs - 0x1000] = data; + else if (lcbank) + language_banks[0][addrs] = data; + else + language_banks[0][addrs + 0x1000] = data; + + ++hexstr; + if (!*hexstr) break; + ++hexstr; + if (++addrs > 0x2fff) return; + } +} + +/* ------------------------------------------------------------------------- + bload () - bload file data into emulator. this is essentially the + same as the set_mem routine. we use the do_write_memory routine to + "safely" set memory... + ------------------------------------------------------------------------- */ +void bload(FILE *f, char *name, int addrs) { + unsigned char *hexstr = NULL; + int len = -1; + unsigned char data; + + if ((addrs < 0) || (addrs > 0xffff)) { + sprintf(second_buf[num_buffer_lines++], "invalid address"); + return; + } + + while ((len = fread(temp, 1, TEMPSIZE, f))) { + hexstr = temp; + for (; len > 0; len--) { + data = *hexstr; + + /* call the set_memory routine, which knows how to route + the request */ + cpu65_direct_write(addrs,data); + + ++hexstr; + if (++addrs > 0xffff) return; /* don't overwrite memory */ + } + } + sprintf(second_buf[num_buffer_lines++], "bloaded: %s", name); +} + + +/* ------------------------------------------------------------------------- + disasm () - disassemble instructions + we DO NOT wrap the display : 0xffff -> 0x0 + ------------------------------------------------------------------------- */ + +void disasm(int addrs, int len, int lc, int rambank) { + static char fmt[64]; + unsigned char op; + char arg1, arg2; + int i, j, k, end, orig_addrs = addrs; + + /* check which rambank for cpu65_current.pc */ + if (rambank == -1) { + rambank = c_get_current_rambank(addrs); + } + + if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000)) + /* read lc anyway */ + lc = 1 + !!(softswitches & SS_BANK2); + + /* handle invalid address request */ + if ((addrs < 0) || (addrs > 0xffff)) { + addrs = cpu65_current.pc; + orig_addrs = addrs; + } + + /* disassembling from language card */ + if (lc) { + if ((addrs >= 0xd000) && (addrs <= 0xffff)) addrs -= 0xd000; + if ((addrs < 0) || (addrs > 0x2fff)) addrs = 0; + } + + if (len > BUF_Y - 2) len = BUF_Y - 2 - num_buffer_lines; + + /* save hexdump in second_buf */ + end = (lc) ? 0x3000 : 0x10000; + for (i = num_buffer_lines, j = addrs, k=orig_addrs; + ((i= 0x1000) ? language_card[rambank][j-0x1000] + : (lc == 1) ? language_banks[rambank][j] + : language_banks[rambank][0x1000+j]; + else + op = apple_ii_64k[rambank][j]; + + switch (opcodes[op].mode) { + case addr_implied: + case addr_accumulator: /* no arg */ + sprintf(second_buf[i], "/%02X/%04X: %02X %s %s", + rambank, k++, op, opcodes[op].mnemonic, + disasm_templates[opcodes[op].mode]); + break; + + case addr_immediate: + case addr_zeropage: + case addr_zeropage_x: + case addr_zeropage_y: + case addr_indirect: + case addr_indirect_x: + case addr_indirect_y: /* byte arg */ + if (k == 0xffff) { + num_buffer_lines = i; + return; + } + + if (lc) + arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000] + : (lc == 1) ? language_banks[rambank][++j] + : language_banks[rambank][++j+0x1000]; + else + arg1 = apple_ii_64k[rambank][++j]; + + sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", + rambank, k, op, (unsigned char)arg1, + opcodes[op].mnemonic, + disasm_templates[opcodes[op].mode]); + + sprintf(second_buf[i], fmt, (unsigned char)arg1); + k+=2; + break; + + case addr_absolute: + case addr_absolute_x: + case addr_absolute_y: + case addr_j_indirect: + case addr_j_indirect_x: /* word arg */ + if (k >= 0xfffe) { + num_buffer_lines = i; + return; + } + + if (lc) { + arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000] + : (lc == 1) ? language_banks[rambank][++j] + : language_banks[rambank][++j+0x1000]; + arg2 = (j >= 0x1000) ? language_card[rambank][++j-0x1000] + : (lc == 1) ? language_banks[rambank][++j] + : language_banks[rambank][++j+0x1000]; + } + else { + arg1 = apple_ii_64k[rambank][++j]; + arg2 = apple_ii_64k[rambank][++j]; + } + + sprintf(fmt, "/%02X/%04X: %02X%02X%02X %s %s", + rambank, k, op, (unsigned char)arg1, (unsigned char)arg2, + opcodes[op].mnemonic, + disasm_templates[opcodes[op].mode]); + sprintf(second_buf[i], fmt, (unsigned char)arg2, + (unsigned char)arg1); + k+=3; + break; + + case addr_relative: /* offset */ + if (k == 0xffff) { + num_buffer_lines = i; + return; + } + + if (lc) + arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000] + : (lc == 1) ? language_banks[rambank][++j] + : language_banks[rambank][++j+0x1000]; + else + arg1 = apple_ii_64k[rambank][++j]; + + sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", + rambank, k, op, (unsigned char)arg1, + opcodes[op].mnemonic, + disasm_templates[opcodes[op].mode]); + if (arg1 < 0) { + sprintf(second_buf[i], fmt, + k + arg1 + 2, '-', (unsigned char)(-arg1)); + } + else { + sprintf(second_buf[i], fmt, + k + arg1 + 2, '+', (unsigned char)arg1); + } + k+=2; + break; + + default: /* shouldn't happen */ + sprintf(second_buf[i], "args to opcode incorrect!"); + break; + } + } + num_buffer_lines = i; +} + +/* ------------------------------------------------------------------------- + show_regs () - shows 6502 registers + ------------------------------------------------------------------------- */ + +void show_regs() { + sprintf(second_buf[num_buffer_lines++], "PC = %04X EA = %04X SP = %04X", + cpu65_current.pc, + cpu65_debug.ea, + cpu65_current.sp + 0x0100); + sprintf(second_buf[num_buffer_lines++], + "X = %02X Y = %02X A = %02X F = %02X", + cpu65_current.x, + cpu65_current.y, + cpu65_current.a, + cpu65_current.f); + + memset(second_buf[num_buffer_lines], ' ', BUF_X); + if (cpu65_current.f & C_Flag) second_buf[num_buffer_lines][0]='C'; + if (cpu65_current.f & X_Flag) second_buf[num_buffer_lines][1]='X'; + if (cpu65_current.f & I_Flag) second_buf[num_buffer_lines][2]='I'; + if (cpu65_current.f & V_Flag) second_buf[num_buffer_lines][3]='V'; + if (cpu65_current.f & B_Flag) second_buf[num_buffer_lines][4]='B'; + if (cpu65_current.f & D_Flag) second_buf[num_buffer_lines][5]='D'; + if (cpu65_current.f & Z_Flag) second_buf[num_buffer_lines][6]='Z'; + if (cpu65_current.f & N_Flag) second_buf[num_buffer_lines][7]='N'; + + ++num_buffer_lines; +} + +/* ------------------------------------------------------------------------- + will_branch () = will instruction branch? + -1 - n/a + 0 - no it won't + >0 - yes it will + ------------------------------------------------------------------------- */ +static int will_branch() { + + unsigned char op = get_current_opcode(); + + switch (op) { + case 0x10: /* BPL */ + return (int) !(cpu65_current.f & N_Flag); + case 0x30: /* BMI */ + return (int) (cpu65_current.f & N_Flag); + case 0x50: /* BVC */ + return (int) !(cpu65_current.f & V_Flag); + case 0x70: /* BVS */ + return (int) (cpu65_current.f & V_Flag); +#ifdef APPLE_IIE + case 0x80: /* BRA */ + return 1; +#endif + case 0x90: /* BCC */ + return (int) !(cpu65_current.f & C_Flag); + case 0xb0: /* BCS */ + return (int) (cpu65_current.f & C_Flag); + case 0xd0: /* BNE */ + return (int) !(cpu65_current.f & Z_Flag); + case 0xf0: /* BEQ */ + return (int) (cpu65_current.f & Z_Flag); + } + + return -1; +} + + +/* ------------------------------------------------------------------------- + set_halt () = set a breakpoint or watchpoint in memory + type = points to "watchpoints" or "breakpoints" array + ------------------------------------------------------------------------- */ +void set_halt(int *type, int addrs) { + int i; + + for (i = 0; i < MAX_BRKPTS; i++) { + if (type[i] == -1) { + type[i] = addrs; + sprintf(second_buf[num_buffer_lines++], "set at %04X", addrs); + return; + } + } + sprintf(second_buf[num_buffer_lines++], "too many!"); +} + +/* ------------------------------------------------------------------------- + clear_halt () = unset a critical breakpoint or watchpoint in memory + type = points to "watchpoints" or "breakpoints" array + pt = (pt - 1) into type. 0 indicates clear all. + ------------------------------------------------------------------------- */ +void clear_halt(int *type, int pt) { + int i; + + if (!pt) { /* unset all */ + for (i = 0; i < MAX_BRKPTS; i++) + type[i] = -1; + return; + } + type[pt-1] = -1; /* unset single */ +} + +/* ------------------------------------------------------------------------- + set_halt_opcode () = set a breakpoint on a particular opcode. + ------------------------------------------------------------------------- */ +void set_halt_opcode(unsigned char opcode) { + op_breakpoints[opcode] = 1; +} + +/* ------------------------------------------------------------------------- + clear_halt_opcode () = unset an opcode breakpoint. + ------------------------------------------------------------------------- */ +void clear_halt_opcode(unsigned char opcode) { + op_breakpoints[opcode] = 0; +} + +#ifdef APPLE_IIE +/* ------------------------------------------------------------------------- + set_halt_65c02 () = set a breakpoint on all 65c02 instructions. + assumes that you are in //e mode... + ------------------------------------------------------------------------- */ +void set_halt_65c02() { + set_halt_opcode((uchar)0x02); set_halt_opcode((uchar)0x04); + set_halt_opcode((uchar)0x0C); set_halt_opcode((uchar)0x12); + set_halt_opcode((uchar)0x14); set_halt_opcode((uchar)0x1A); + set_halt_opcode((uchar)0x1C); set_halt_opcode((uchar)0x32); + set_halt_opcode((uchar)0x34); set_halt_opcode((uchar)0x3A); + set_halt_opcode((uchar)0x3C); set_halt_opcode((uchar)0x52); + set_halt_opcode((uchar)0x5A); set_halt_opcode((uchar)0x64); + set_halt_opcode((uchar)0x72); set_halt_opcode((uchar)0x74); + set_halt_opcode((uchar)0x7A); set_halt_opcode((uchar)0x7C); + set_halt_opcode((uchar)0x80); set_halt_opcode((uchar)0x89); + set_halt_opcode((uchar)0x92); set_halt_opcode((uchar)0x9C); + set_halt_opcode((uchar)0x9E); set_halt_opcode((uchar)0xB2); + set_halt_opcode((uchar)0xD2); set_halt_opcode((uchar)0xDA); + set_halt_opcode((uchar)0xF2); set_halt_opcode((uchar)0xFA); +} + +/* ------------------------------------------------------------------------- + clear_halt_65c02 () = clear all 65c02 instructions + ------------------------------------------------------------------------- */ +void clear_halt_65c02() { + clear_halt_opcode((uchar)0x02); clear_halt_opcode((uchar)0x04); + clear_halt_opcode((uchar)0x0C); clear_halt_opcode((uchar)0x12); + clear_halt_opcode((uchar)0x14); clear_halt_opcode((uchar)0x1A); + clear_halt_opcode((uchar)0x1C); clear_halt_opcode((uchar)0x32); + clear_halt_opcode((uchar)0x34); clear_halt_opcode((uchar)0x3A); + clear_halt_opcode((uchar)0x3C); clear_halt_opcode((uchar)0x52); + clear_halt_opcode((uchar)0x5A); clear_halt_opcode((uchar)0x64); + clear_halt_opcode((uchar)0x72); clear_halt_opcode((uchar)0x74); + clear_halt_opcode((uchar)0x7A); clear_halt_opcode((uchar)0x7C); + clear_halt_opcode((uchar)0x80); clear_halt_opcode((uchar)0x89); + clear_halt_opcode((uchar)0x92); clear_halt_opcode((uchar)0x9C); + clear_halt_opcode((uchar)0x9E); clear_halt_opcode((uchar)0xB2); + clear_halt_opcode((uchar)0xD2); clear_halt_opcode((uchar)0xDA); + clear_halt_opcode((uchar)0xF2); clear_halt_opcode((uchar)0xFA); +} +#endif + +/* ------------------------------------------------------------------------- + at_haltpt () - tests if at haltpt + returns 0 = no breaks or watches + 1 = one break or watchpoint fired + n = two or more breaks and/or watches fired + ------------------------------------------------------------------------- */ +int at_haltpt() { + int i; + + /* check op_breakpoints */ + unsigned char op = get_current_opcode(); + if (op_breakpoints[op]) + sprintf(second_buf[num_buffer_lines++], + "stopped at %04X bank %d instruction %02X", + cpu65_current.pc, c_get_current_rambank(cpu65_current.pc), op); + + for (i = 0; i < MAX_BRKPTS; i++) { + + if (cpu65_current.pc == breakpoints[i]) { + sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d", + breakpoints[i], c_get_current_rambank(cpu65_current.pc)); + } + } + + if (cpu65_debug.op) /* only check watchpoints if read/write occured */ + { + for (i = 0; i < MAX_BRKPTS; i++) { + if (cpu65_debug.ea == watchpoints[i]) { + if (cpu65_debug.op & 2) { + sprintf(second_buf[num_buffer_lines++], + "wrote: %04X: %02X", + watchpoints[i], cpu65_debug.d); + } + else { + sprintf(second_buf[num_buffer_lines++], + "read: %04X", watchpoints[i]); + } + cpu65_debug.op = 0; /* only allow WP to trip once */ + } + } + } + return num_buffer_lines; /* 0 indicates nothing happened */ +} + +/* ------------------------------------------------------------------------- + show_breakpts () - show breakpoints and watchpoints + ------------------------------------------------------------------------- */ +void show_breakpts() { + int i=num_buffer_lines, k; + + for (k = 0; k < MAX_BRKPTS; k++) { + if ((breakpoints[k] >= 0) && (watchpoints[k] >= 0)) { + sprintf(second_buf[i++], "break %02d at %04X watch %02d at %04X", + k+1, breakpoints[k], k+1, watchpoints[k]); + } + else if (breakpoints[k] >= 0) { + sprintf(second_buf[i++], "break %02d at %04X", + k+1, breakpoints[k]); + } + else if (watchpoints[k] >= 0) { + memset(second_buf[i], ' ', BUF_X); + sprintf(second_buf[i++]+16, " watch %02d at %04X", + k+1, watchpoints[k]); + } + } + num_buffer_lines = i; +} + +/* ------------------------------------------------------------------------- + show_opcode_breakpts () - show opcode breakpoints + ------------------------------------------------------------------------- */ +void show_opcode_breakpts() { + int i=num_buffer_lines, k; + + sprintf(second_buf[i++], " 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + sprintf(second_buf[i++], " |-------------------------------|"); + for (k = 0; k < 0x10; k++) { + sprintf(second_buf[i++], + " %X|%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s|", k, + op_breakpoints[k ] ? "x" : " ", + op_breakpoints[k+0x10] ? "x" : " ", + op_breakpoints[k+0x20] ? "x" : " ", + op_breakpoints[k+0x30] ? "x" : " ", + op_breakpoints[k+0x40] ? "x" : " ", + op_breakpoints[k+0x50] ? "x" : " ", + op_breakpoints[k+0x60] ? "x" : " ", + op_breakpoints[k+0x70] ? "x" : " ", + op_breakpoints[k+0x80] ? "x" : " ", + op_breakpoints[k+0x90] ? "x" : " ", + op_breakpoints[k+0xA0] ? "x" : " ", + op_breakpoints[k+0xB0] ? "x" : " ", + op_breakpoints[k+0xC0] ? "x" : " ", + op_breakpoints[k+0xD0] ? "x" : " ", + op_breakpoints[k+0xE0] ? "x" : " ", + op_breakpoints[k+0xF0] ? "x" : " "); + } + sprintf(second_buf[i++], " |-------------------------------|"); + + num_buffer_lines = i; +} + +/* ------------------------------------------------------------------------- + show_lc_info () - show language card info + ------------------------------------------------------------------------- */ +void show_lc_info() { + int i = num_buffer_lines; + sprintf(second_buf[i++], "lc bank = %d", 1 + !!(softswitches && SS_BANK2)); + (softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC") + : sprintf(second_buf[i++], "LC write protected"); + (softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC") + : sprintf(second_buf[i++], "read ROM"); + sprintf(second_buf[i++], "second = %d", !! (softswitches && SS_LCSEC)); + num_buffer_lines = i; +} + +void show_misc_info() { + int i = num_buffer_lines; + sprintf(second_buf[i++], "TEXT (%04X): %s", + SW_TEXT + !!(softswitches & SS_TEXT), + (softswitches & SS_TEXT) ? "on" : "off"); + sprintf(second_buf[i++], "MIXED (%04X): %s", + SW_MIXED + !!(softswitches & SS_MIXED), + (softswitches & SS_MIXED) ? "on" : "off"); + sprintf(second_buf[i++], "PAGE2 (%04X): %s", + SW_PAGE2 + !!(softswitches & SS_PAGE2), + (softswitches & SS_PAGE2) ? "on" : "off"); + sprintf(second_buf[i++], "HIRES (%04X): %s", + SW_HIRES + !!(softswitches & SS_HIRES), + (softswitches & SS_HIRES) ? "on" : "off"); +#ifdef APPLE_IIE + sprintf(second_buf[i++], "80STORE (%04X): %s", + SW_80STORE + !!(softswitches & SS_80STORE), + (softswitches & SS_80STORE) ? "on" : "off"); + sprintf(second_buf[i++], "RAMRD (%04X): %s", + SW_RAMRD + !!(softswitches & SS_RAMRD), + (softswitches & SS_RAMRD) ? "on" : "off"); + sprintf(second_buf[i++], "RAMWRT (%04X): %s", + SW_RAMWRT + !!(softswitches & SS_RAMWRT), + (softswitches & SS_RAMWRT) ? "on" : "off"); + sprintf(second_buf[i++], "ALTZP (%04X): %s", + SW_ALTZP + !!(softswitches & SS_ALTZP), + (softswitches & SS_ALTZP) ? "on" : "off"); + sprintf(second_buf[i++], "80COL (%04X): %s", + SW_80COL + !!(softswitches & SS_80COL), + (softswitches & SS_80COL) ? "on" : "off"); + sprintf(second_buf[i++], "ALTCHAR (%04X): %s", + SW_ALTCHAR + !!(softswitches & SS_ALTCHAR), + (softswitches & SS_ALTCHAR) ? "on" : "off"); + sprintf(second_buf[i++], "SLOTC3ROM (%04X): %s", + SW_SLOTC3ROM -/*anomaly*/ !!(softswitches & SS_C3ROM), + (softswitches & SS_C3ROM) ? "on" : "off"); + sprintf(second_buf[i++], "SLOTCXROM (%04X): %s", + SW_SLOTCXROM + !!(softswitches & SS_CXROM), + (softswitches & SS_CXROM) ? "on" : "off"); + sprintf(second_buf[i++], "DHIRES (%04X): %s", + SW_DHIRES + !!(softswitches && SS_DHIRES), + (softswitches & SS_DHIRES) ? "on" : "off"); + sprintf(second_buf[i++], "IOUDIS (%04X): %s", + SW_IOUDIS + !!(softswitches && SS_IOUDIS), + (softswitches && SS_IOUDIS) ? "on" : "off"); +/* sprintf(second_buf[i++], "RDVBLBAR: %s", (SLOTCXROM & 0x80) */ +/* ? "on" : "off"); */ + +#endif + num_buffer_lines = i; +} + +/* ------------------------------------------------------------------------- + show_disk_info () - disk II info + ------------------------------------------------------------------------- */ +void show_disk_info() { + static char tmp[32]; + int i = num_buffer_lines, len = 0, off = 19; + + /* generic information */ + sprintf(second_buf[i++], "drive %s", (disk6.drive) ? "B" : "A"); + sprintf(second_buf[i++], "motor %s", (disk6.motor) ? "off" : "on"); + sprintf(second_buf[i++], "%s", (disk6.ddrw) ? "write" : "read"); + sprintf(second_buf[i++], "byte = %02X", disk6.disk_byte); + if (!disk6.disk[disk6.drive].nibblized) { + sprintf(second_buf[i++], "volume = %d", disk6.volume); + sprintf(second_buf[i++], "checksum = %d", disk6.checksum); + } + + sprintf(second_buf[i++], "-------------------------------------"); + + /* drive / image specific information */ + memset(second_buf[i], ' ', BUF_X); + if ((len = strlen(disk6.disk[0].file_name))) { + while ((--len) && (disk6.disk[0].file_name[len] != '/')); + strncpy(tmp, disk6.disk[0].file_name + len + 1, 31); + *(second_buf[i] + sprintf(second_buf[i], "%s", tmp)) = ' '; + } + + if ((len = strlen(disk6.disk[1].file_name))) { + while ((--len) && (disk6.disk[1].file_name[len] != '/')); + strncpy(tmp, disk6.disk[1].file_name + len + 1, 31); + sprintf(second_buf[i]+off, "%s", tmp); + } + + memset(second_buf[++i], ' ', BUF_X); + *(second_buf[i] + sprintf(second_buf[i], + "%s %d bytes", + (disk6.disk[0].nibblized) ? ".nib" : ".dsk", + (int)disk6.disk[0].file_size)) = ' '; + sprintf(second_buf[i++]+off, "%s %d bytes", + (disk6.disk[1].nibblized) ? ".nib" : ".dsk", + (int)disk6.disk[1].file_size); + + memset(second_buf[i], ' ', BUF_X); + *(second_buf[i] + sprintf(second_buf[i], "write %s", + (disk6.disk[0].protected) ? "protected" : "enabled")) = ' '; + sprintf(second_buf[i++]+off, "write %s", + (disk6.disk[1].protected) ? "protected" : "enabled"); + + memset(second_buf[i], ' ', BUF_X); + *(second_buf[i] + sprintf(second_buf[i], + "phase %d %s", + disk6.disk[0].phase, + (disk6.disk[0].phase_change) ? "(new)" : "")) = ' '; + sprintf(second_buf[i++]+off, + "phase %d %s", + disk6.disk[1].phase, + (disk6.disk[1].phase_change) ? "(new)" : ""); + + memset(second_buf[i], ' ', BUF_X); + if (!disk6.disk[0].nibblized) { + *(second_buf[i] + sprintf(second_buf[i], "sector %d", + disk6.disk[0].sector)) = ' '; + if (disk6.disk[1].nibblized) ++i; + } + if (!disk6.disk[1].nibblized) + sprintf(second_buf[i++]+off, "sector %d", + disk6.disk[1].sector); + + num_buffer_lines = i; +} + +/* ------------------------------------------------------------------------- + clear_debugger_screen () - clears the screen of graphics artifacts. + ------------------------------------------------------------------------- */ +void clear_debugger_screen() { + int i; + video_setpage( 0 ); + for (i = 0; i < 24; i++) + c_interface_print(0, i, 2, screen[ i ] ); +} + +/* ------------------------------------------------------------------------- + end_step () - finish a stepping command + display the next instruction, and tell whether it will branch + ------------------------------------------------------------------------- */ +void end_step() { + int branch; + + clear_debugger_screen(); + disasm(cpu65_current.pc, 1, 0, -1); /* show next instruction */ + branch = will_branch(); /* test if it will branch */ + if (branch == -1) return; /* n/a */ + sprintf(second_buf[num_buffer_lines++], "%s", + (branch) ? "will branch" : "will not branch"); +} + +/* ------------------------------------------------------------------------- + c_do_step () - step into or step over commands + ------------------------------------------------------------------------- */ +void c_do_step(int step_count) { + char ch; + unsigned char op; + int step_frame = 0; + + /* do step while step_count AND no breaks AND no keypress */ + do { + op = get_current_opcode(); + + if (step_next && (op == 0x20)) { + do { + op = get_current_opcode(); + if (op == 0x20) ++step_frame;/* JSR */ + if (op == 0x60) --step_frame;/* RTS */ + cpu65_step(); + } while (((ch = c_mygetch(0)) == -1) && !at_haltpt() && step_frame); + } + else cpu65_step(); /* step one instruction */ + } while (--step_count && !at_haltpt() && (c_mygetch(0) == -1)); + + end_step(); /* print location */ +} + +/* ------------------------------------------------------------------------- + display_help () + show quick reference command usage + ------------------------------------------------------------------------- */ +void display_help() { + /* "|||||||||||||||||||||||||||||||||||||" */ + int i = num_buffer_lines; + sprintf(second_buf[i++], "d{is} {lc1|lc2} {/bank/addr} {+}{len}"); + sprintf(second_buf[i++], "m{em} {lc1|lc2} {/bank/addr} {+}{len}"); + sprintf(second_buf[i++], "a{sc} {lc1|lc2} {/bank/addr} {+}{len}"); + sprintf(second_buf[i++], "r{egs} "); + sprintf(second_buf[i++], " {lc1|lc2} : "); + sprintf(second_buf[i++], "(s{tep} | n{ext}) {len} "); + sprintf(second_buf[i++], "f{inish} "); + sprintf(second_buf[i++], "u{ntil} "); + sprintf(second_buf[i++], "g{o} {addr} "); + sprintf(second_buf[i++], "sea{rch} {lc1|lc2} {bank} "); + sprintf(second_buf[i++], "(b{reak} | w{atch}) {addr} "); + sprintf(second_buf[i++], "b{reak} op "); + sprintf(second_buf[i++], "(c{lear} | i{gnore}) {num} "); + sprintf(second_buf[i++], "c{lear} op "); + sprintf(second_buf[i++], "(sta{tus} | op{codes}) "); + sprintf(second_buf[i++], "(l{ang} | d{rive} | vm) "); + sprintf(second_buf[i++], "bsave "); + sprintf(second_buf[i++], "bload "); + sprintf(second_buf[i++], "fr{esh} "); + sprintf(second_buf[i++], "(h{elp} | ?) "); + num_buffer_lines = i; +} + + +/* ------------------------------------------------------------------------- + do_debug_command () + perform a debugger command + ------------------------------------------------------------------------- */ + +void do_debug_command() { + int i = 0, j = 0, k = 0; + + /* reset key local vars */ + step_next = 0; + num_buffer_lines = 0; + + /* call lex to perform the command.*/ + strncpy(lexbuf, command_line + PROMPT_X, BUF_X); + init_lex(lexbuf, BUF_X+2); + debuglex(); + + /* set up to copy results into main buffer */ + if (num_buffer_lines >= PROMPT_Y) { + k = BUF_Y - PROMPT_Y; + } else { + /* scroll buffer */ + for (i = 0, j = 0; i < PROMPT_Y - num_buffer_lines; i++, j = 0) { + memcpy(command_buf[i], command_buf[num_buffer_lines+1+i], BUF_X); + while ((j < BUF_X) && (command_buf[i][j] != '\0')) j++; + memset (command_buf[i] + j, ' ', BUF_X - j); + command_buf[i][BUF_X - 1] = '\0'; + } + } + + /* copy the debug results into debug console window. change '\0's + to ' 's and cap with a single '\0' */ + while (i < PROMPT_Y) { + j = 0; + memcpy(command_buf[i], second_buf[k++], BUF_X); + while ((j < BUF_X) && (command_buf[i][j] != '\0')) ++j; + memset(command_buf[i] + j, ' ', BUF_X - j); + command_buf[i++][BUF_X - 1] = '\0'; + } + + /* new prompt */ + memset(command_line, ' ', BUF_X); + command_line[0] = '>'; + command_line[BUF_X - 1] = '\0'; + + /* display the new information */ + for (i=0; i PROMPT_X)) { + command_line[--command_pos] = ' '; + } + /* return */ + else if (ch == 13) { + command_line[command_pos] = '\0'; + do_debug_command(); + command_pos = PROMPT_X; + } + /* normal character */ + else if ((ch >= ' ') && (ch < 127) && + (command_pos < PROMPT_END_X)) { + command_line[command_pos++] = ch; + } + } + } +} + +#endif /* DEBUGGER */ diff --git a/src/disk.c b/src/disk.c new file mode 100644 index 00000000..54dda446 --- /dev/null +++ b/src/disk.c @@ -0,0 +1,671 @@ +/* + * Apple // emulator for Linux: C portion of Disk ][ emulation + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "disk.h" +#include "misc.h" +#include "cpu.h" +#include "glue.h" +#include "prefs.h" + +#define PHASE_BYTES 3328 + +static unsigned char slot6_rom[256]; +static int slot6_rom_loaded = 0; + +struct drive disk6; + +static int skew_table_6[16] = /* Sector skew table */ + { 0,7,14,6,13,5,12,4,11,3,10,2,9,1,8,15 }; + +static int translate_table_6[256] =/* Translation table */ + { + 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6, + 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3, + 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01, + 0x80, 0x80, 0x02, 0x03, 0x80, 0x04, 0x05, 0x06, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x07, 0x08, + 0x80, 0x80, 0x80, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x80, 0x80, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x80, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x1b, 0x80, 0x1c, 0x1d, 0x1e, + 0x80, 0x80, 0x80, 0x1f, 0x80, 0x80, 0x20, 0x21, + 0x80, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x29, 0x2a, 0x2b, + 0x80, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x80, 0x80, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x80, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f + }; + +/* ------------------------------------------------------------------------- + c_init_6() + ------------------------------------------------------------------------- */ + +void c_init_6() +{ + disk6.disk[0].phase = disk6.disk[1].phase = 42; + disk6.disk[0].phase_change = disk6.disk[1].phase_change = 0; + + disk6.motor = 1; /* motor on */ + disk6.drive = 0; /* first drive active */ + disk6.ddrw = 0; + disk6.volume = 254; +#if 0 /* BUGS!: */ + file_name_6[0][1024] = '\0'; + file_name_6[1][1024] = '\0'; +#endif +} + +/* ------------------------------------------------------------------------- + c_eject_6() - assumes privileged access to image file (to re-gzip) + ------------------------------------------------------------------------- */ + +void c_eject_6(int drive) { + pid_t pid; + + if (disk6.disk[drive].compressed) { + /* gzip the last disk if it was compressed_6 */ + if ((pid = fork())) { /* parent process */ + /* privileged mode - gzip in place */ + waitpid(pid, NULL, 0); + } else if (!pid) { /* child process */ + /* privileged mode - gzip in place */ + if (execl("/bin/gzip", "/bin/gzip", + disk6.disk[drive].file_name, NULL) == -1) + { + perror("Problem exec'ing /bin/gzip"); + exit(-1); + } + } else { + perror("Problem calling fork" ); + } + } + disk6.disk[drive].compressed = 0; + disk6.disk[drive].nibblized = 0; + sprintf(disk6.disk[drive].file_name, "%s", ""); + if (disk6.disk[drive].fp) { + fclose(disk6.disk[drive].fp); + disk6.disk[drive].fp = NULL; + } +} + +/* ------------------------------------------------------------------------- + c_new_diskette_6( int drive, char *filename, Tr cmpr, Tr nib ) + inserts a new disk image into the appropriate drive. assumes + privileged user level on entry, sets to the user when using disks. + return 1 if we can't open an image file for reading. + ------------------------------------------------------------------------- */ + +int c_new_diskette_6(int drive, char *file_name, int cmpr, int nib, int force) { + struct stat buf; + + strcpy(disk6.disk[drive].file_name, file_name); + disk6.disk[drive].compressed = cmpr; + disk6.disk[drive].nibblized = nib; + if (disk6.disk[drive].fp) { + fclose(disk6.disk[drive].fp); + disk6.disk[drive].fp = NULL; + } + /* set to users privilege level for disk access */ + + if (stat(disk6.disk[drive].file_name, &buf) < 0) { + disk6.disk[drive].fp = NULL; + c_eject_6(drive); + return 1; /* problem: disk unreadable */ + } + else { + disk6.disk[drive].file_size = buf.st_size; + + if (!force) { + /* Open read only */ + disk6.disk[drive].fp = fopen(disk6.disk[drive].file_name, "r+"); + disk6.disk[drive].protected = 0; + } + if ((disk6.disk[drive].fp == NULL) || (force)) { + /* Open for read AND write */ + disk6.disk[drive].fp = fopen(disk6.disk[drive].file_name, "r"); + disk6.disk[drive].protected = 1; /* disk is write protected! */ + } + if (disk6.disk[drive].fp == NULL) { + /* Failed to open file. */ + c_eject_6(drive); + return 1; /* problem: disk unreadable */ + } + /* seek to current head position. */ + fseek(disk6.disk[drive].fp, PHASE_BYTES * disk6.disk[drive].phase, SEEK_SET); + } + + disk6.disk[drive].sector = 0; + disk6.disk[drive].run_byte = 0; + + return 0; /* no problem */ +} + + +/* ------------------------------------------------------------------------- + c_read_nibblized_6_6() - reads a standard .nib file of length 232960 bytes. + + there are 70 phases positioned every 3328 bytes. + ------------------------------------------------------------------------- */ + +unsigned char c_read_nibblized_6_6() +{ + static unsigned char ch; + + if (disk6.disk[disk6.drive].phase_change) { + fseek(disk6.disk[disk6.drive].fp, PHASE_BYTES * disk6.disk[disk6.drive].phase, SEEK_SET); + disk6.disk[disk6.drive].phase_change = 0; + } + ch = (unsigned char) disk6.disk_byte = fgetc(disk6.disk[disk6.drive].fp); + /* track revolves... */ + if (ftell(disk6.disk[disk6.drive].fp) == (PHASE_BYTES * (disk6.disk[disk6.drive].phase + 2))) + fseek(disk6.disk[disk6.drive].fp, -2 * PHASE_BYTES, SEEK_CUR); + + return ch; +} + +/* ------------------------------------------------------------------------- + c_read_normal_6() + ------------------------------------------------------------------------- */ +unsigned char c_read_normal_6() +{ + int position; + int old_value; + + unsigned char value = 0; + + /* The run byte tells what's to do */ + switch (disk6.disk[disk6.drive].run_byte) + { + case 0: case 1: case 2: case 3: case 4: case 5: + case 20: case 21: case 22: case 23: case 24: + /* Sync */ + value = 0xFF; + break; + + case 6: case 25: + /* Prologue (first byte) */ + value = 0xD5; + break; + + case 7: case 26: + /* Prologue (second byte) */ + value = 0xAA; + break; + + case 8: + /* Prologue (third byte) */ + value = 0x96; + break; + + case 9: + /* Volume (encoded) */ + value = (disk6.volume >> 1) | 0xAA; + disk6.checksum = disk6.volume; + break; + + case 10: + /* Volume (encoded) */ + value = disk6.volume | 0xAA; + break; + + case 11: + /* Track number (encoded) */ + disk6.checksum ^= (disk6.disk[disk6.drive].phase >> 1); + value = (disk6.disk[disk6.drive].phase >> 2) | 0xAA; + break; + + case 12: + /* Track number (encoded) */ + value = (disk6.disk[disk6.drive].phase >> 1) | 0xAA; + break; + + case 13: + /* Sector number (encoded) */ + disk6.checksum ^= disk6.disk[disk6.drive].sector; + value = (disk6.disk[disk6.drive].sector >> 1) | 0xAA; + break; + + case 14: + /* Sector number (encoded) */ + value = disk6.disk[disk6.drive].sector | 0xAA; + break; + + case 15: + /* Checksum */ + value = (disk6.checksum >> 1) | 0xAA; + break; + + case 16: + /* Checksum */ + value = disk6.checksum | 0xAA; + break; + + case 17: case 371: + /* Epilogue (first byte) */ + value = 0xDE; + break; + + case 18: case 372: + /* Epilogue (second byte) */ + value = 0xAA; + break; + + case 19: case 373: + /* Epilogue (third byte) */ + value = 0xEB; + break; + + case 27: + /* Data header */ + disk6.exor_value = 0; + + /* Set file position variable */ + disk6.disk[disk6.drive].file_pos = 256 * 16 * (disk6.disk[disk6.drive].phase >> 1) + + 256 * skew_table_6[ disk6.disk[disk6.drive].sector ]; + + /* File large enough? */ + if (disk6.disk[disk6.drive].file_pos + 255 > disk6.disk[disk6.drive].file_size) + return 0xFF; + + /* Set position */ + fseek( disk6.disk[disk6.drive].fp, disk6.disk[disk6.drive].file_pos, SEEK_SET ); + + /* Read sector */ + fread( disk6.disk_data, 1, 256, disk6.disk[disk6.drive].fp ); + disk6.disk_data[ 256 ] = disk6.disk_data[ 257 ] = 0; + value = 0xAD; + break; + + case 370: + /* Checksum */ + value = translate_table_6[disk6.exor_value & 0x3F]; + + /* Increment sector number (and wrap if necessary) */ + disk6.disk[disk6.drive].sector++; + if (disk6.disk[disk6.drive].sector == 16) + disk6.disk[disk6.drive].sector = 0; + + break; + + default: + position = disk6.disk[disk6.drive].run_byte - 28; + if (position >= 0x56) + { + position -= 0x56; + old_value = disk6.disk_data[ position ]; + old_value = old_value >> 2; + disk6.exor_value ^= old_value; + value = translate_table_6[disk6.exor_value & 0x3F]; + disk6.exor_value = old_value; + } + else + { + old_value = 0; + old_value |= (disk6.disk_data[position] & 0x1) << 1; + old_value |= (disk6.disk_data[position] & 0x2) >> 1; + old_value |= (disk6.disk_data[position+0x56] & 0x1) << 3; + old_value |= (disk6.disk_data[position+0x56] & 0x2) << 1; + old_value |= (disk6.disk_data[position+0xAC] & 0x1) << 5; + old_value |= (disk6.disk_data[position+0xAC] & 0x2) << 3; + disk6.exor_value ^= old_value; + value = translate_table_6[disk6.exor_value & 0x3F]; + disk6.exor_value = old_value; + } + break; + } /* End switch */ + + /* Continue by increasing run byte value */ + disk6.disk[disk6.drive].run_byte++; + if (disk6.disk[disk6.drive].run_byte > 373) + disk6.disk[disk6.drive].run_byte = 0; + + disk6.disk_byte = value; + return value; +} + + + +/* ------------------------------------------------------------------------- + c_write_nibblized_6_6() - writes a standard .nib file of length 232960 bytes. + + there are 70 phases positioned every 3328 bytes. + ------------------------------------------------------------------------- */ + +void c_write_nibblized_6_6() +{ + if (disk6.disk[disk6.drive].phase_change) { + fseek(disk6.disk[disk6.drive].fp, PHASE_BYTES * disk6.disk[disk6.drive].phase, SEEK_SET); + disk6.disk[disk6.drive].phase_change = 0; + } + fputc(disk6.disk_byte, disk6.disk[disk6.drive].fp); + /* track revolves... */ + if (ftell(disk6.disk[disk6.drive].fp) == (PHASE_BYTES * (disk6.disk[disk6.drive].phase + 2))) + fseek(disk6.disk[disk6.drive].fp, -2 * PHASE_BYTES, SEEK_CUR); +} + +/* ------------------------------------------------------------------------- + c_write_normal_6() disk6.disk_byte contains the value + ------------------------------------------------------------------------- */ + +void c_write_normal_6() +{ + int position; + int old_value; + + if (disk6.disk_byte == 0xD5) + disk6.disk[disk6.drive].run_byte = 6; /* Initialize run byte value */ + + /* The run byte tells what's to do */ + + switch (disk6.disk[disk6.drive].run_byte) + { + case 0: case 1: case 2: case 3: case 4: case 5: + case 20: case 21: case 22: case 23: case 24: + /* Sync */ + break; + + case 6: case 25: + /* Prologue (first byte) */ + if (disk6.disk_byte == 0xFF) + disk6.disk[disk6.drive].run_byte--; + break; + + case 7: case 26: + /* Prologue (second byte) */ + break; + + case 8: + /* Prologue (third byte) */ + if (disk6.disk_byte == 0xAD) + disk6.exor_value = 0, disk6.disk[disk6.drive].run_byte = 27; + break; + + case 9: case 10: + /* Volume */ + break; + + case 11: case 12: + /* Track */ + break; + + case 13: case 14: + /* Sector */ + break; + + case 15: + /* Checksum */ + break; + + case 16: + /* Checksum */ + break; + + case 17: case 371: + /* Epilogue (first byte) */ + break; + + case 18: case 372: + /* Epilogue (second byte) */ + break; + + case 19: case 373: + /* Epilogue (third byte) */ + break; + + case 27: + disk6.exor_value = 0; + break; + + case 370: + /* Set file position variable */ + disk6.disk[disk6.drive].file_pos = 256 * 16 * (disk6.disk[disk6.drive].phase >> 1) + + 256 * skew_table_6[ disk6.disk[disk6.drive].sector ]; + + /* Is the file large enough? */ + if (disk6.disk[disk6.drive].file_pos + 255 > disk6.disk[disk6.drive].file_size) + return; + + + /* Set position */ + fseek( disk6.disk[disk6.drive].fp, disk6.disk[disk6.drive].file_pos, SEEK_SET ); + + /* Write sector */ + fwrite(disk6.disk_data, 1, 256, disk6.disk[disk6.drive].fp); + fflush( disk6.disk[disk6.drive].fp ); + /* Increment sector number (and wrap if necessary) */ + disk6.disk[disk6.drive].sector++; + if (disk6.disk[disk6.drive].sector == 16) + disk6.disk[disk6.drive].sector = 0; + break; + + default: + position = disk6.disk[disk6.drive].run_byte - 28; + disk6.disk_byte = translate_table_6[ disk6.disk_byte ]; + if (position >= 0x56) + { + position -= 0x56; + disk6.disk_byte ^= disk6.exor_value; + old_value = disk6.disk_byte; + disk6.disk_data[position] |= (disk6.disk_byte << 2) & 0xFC; + disk6.exor_value = old_value; + } + else + { + disk6.disk_byte ^= disk6.exor_value; + old_value = disk6.disk_byte; + disk6.disk_data[position] = (disk6.disk_byte & 0x01) << 1; + disk6.disk_data[position] |= (disk6.disk_byte & 0x02) >> 1; + disk6.disk_data[position + 0x56] = (disk6.disk_byte & 0x04) >> 1; + disk6.disk_data[position + 0x56] |= (disk6.disk_byte & 0x08) >> 3; + disk6.disk_data[position + 0xAC] = (disk6.disk_byte & 0x10) >> 3; + disk6.disk_data[position + 0xAC] |= (disk6.disk_byte & 0x20) >> 5; + disk6.exor_value = old_value; + } + break; + } /* End switch */ + + disk6.disk[disk6.drive].run_byte++; + if (disk6.disk[disk6.drive].run_byte > 373) + disk6.disk[disk6.drive].run_byte = 0; +} + +GLUE_C_READ(disk_read_byte) +{ + if (disk6.ddrw) + { + if (disk6.disk[disk6.drive].fp == NULL) + return 0; /* Return if there is no disk in drive */ + if (disk6.disk[disk6.drive].protected) + return 0; /* Do not write if diskette is write protected */ + + if (disk6.disk_byte < 0x96) + return 0; /* Only byte values at least 0x96 are allowed */ + + (disk6.disk[disk6.drive].nibblized) ? c_write_nibblized_6_6() : c_write_normal_6(); + return 0; /* ??? */ + } + else + { + if (disk6.disk[disk6.drive].fp == NULL) + return 0xFF; /* Return FF if there is no disk in drive */ + + if (disk6.motor) /* Motor turned on? */ + { + if (disk6.motor > 99) + return 0; + else + disk6.motor++; + } + + /* handle nibblized_6 or regular disks */ + return (disk6.disk[disk6.drive].nibblized) ? c_read_nibblized_6_6() : c_read_normal_6() ; + } +} + +GLUE_C_READ(disk_read_phase) +{ + /* + * Comment from xapple2+ by Phillip Stephens: + * Turn motor phases 0 to 3 on. Turning on the previous phase + 1 + * increments the track position, turning on the previous phase - 1 + * decrements the track position. In this scheme phase 0 and 3 are + * considered to be adjacent. The previous phase number can be + * computed as the track number % 4. + */ + + switch (((ea >> 1) - disk6.disk[disk6.drive].phase) & 3) + { + case 1: + disk6.disk[disk6.drive].phase++; + break; + case 3: + disk6.disk[disk6.drive].phase--; + break; + } + + if (disk6.disk[disk6.drive].phase<0) disk6.disk[disk6.drive].phase=0; + if (disk6.disk[disk6.drive].phase>69) disk6.disk[disk6.drive].phase=69; + + disk6.disk[disk6.drive].phase_change = 1; + + return 0; +} + + +GLUE_C_READ(disk_read_motor_off) +{ + disk6.motor = 1; + return disk6.drive; +} + +GLUE_C_READ(disk_read_motor_on) +{ + disk6.motor = 0; + return disk6.drive; +} + +GLUE_C_READ(disk_read_select_a) +{ + return disk6.drive = 0; +} + +GLUE_C_READ(disk_read_select_b) +{ + return disk6.drive = 1; +} + + +GLUE_C_READ(disk_read_latch) +{ + return disk6.drive; +} + +GLUE_C_READ(disk_read_prepare_in) +{ + disk6.ddrw = 0; + return disk6.disk[disk6.drive].protected ? 0x80 : 0x00; +} + +GLUE_C_READ(disk_read_prepare_out) +{ + disk6.ddrw = 1; + return disk6.drive; +} + +GLUE_C_WRITE(disk_write_latch) +{ + disk6.disk_byte = d; +} + +void disk_install(int slot) +{ + FILE *f; + int i; + + assert(slot == 6); + + /* load Disk II rom */ + if (!slot6_rom_loaded) { + snprintf(temp, TEMPSIZE, "%s/slot6.rom", system_path); + if ((f = fopen( temp, "r" )) == NULL) { + printf("Cannot find file '%s'.\n",temp); + exit( 0 ); + } + fread(slot6_rom, 0x100, 1, f); + fclose(f); + slot6_rom_loaded = 1; + } + memcpy(apple_ii_64k[0] + 0xC600, slot6_rom, 0x100); + + /* disk softswitches */ + cpu65_vmem[0xC0E0].r = cpu65_vmem[0xC0E2].r = + cpu65_vmem[0xC0E4].r = cpu65_vmem[0xC0E6].r = + ram_nop; + + cpu65_vmem[0xC0E1].r = cpu65_vmem[0xC0E3].r = + cpu65_vmem[0xC0E5].r = cpu65_vmem[0xC0E7].r = + disk_read_phase; + + cpu65_vmem[0xC0E8].r = + disk_read_motor_off; + cpu65_vmem[0xC0E9].r = + disk_read_motor_on; + cpu65_vmem[0xC0EA].r = + disk_read_select_a; + cpu65_vmem[0xC0EB].r = + disk_read_select_b; + cpu65_vmem[0xC0EC].r = + disk_read_byte; + cpu65_vmem[0xC0ED].r = + disk_read_latch; /* read latch */ + cpu65_vmem[0xC0EE].r = + disk_read_prepare_in; + cpu65_vmem[0xC0EF].r = + disk_read_prepare_out; + + for (i = 0xC0E0; i < 0xC0F0; i++) { + cpu65_vmem[i].w = + cpu65_vmem[i].r; + } + + cpu65_vmem[0xC0ED].w = + disk_write_latch; /* write latch */ +} diff --git a/src/disk.h b/src/disk.h new file mode 100644 index 00000000..f92feb60 --- /dev/null +++ b/src/disk.h @@ -0,0 +1,67 @@ +/* + * Apple // emulator for Linux: Defines for Disk ][ emulation + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + + +#ifndef A2_DISK_H + +struct diskette +{ + unsigned char file_name[1024]; + int compressed; + int nibblized; + int protected; + int phase_change; + int sector; + long file_size; + int phase; + int run_byte; + FILE *fp; + int file_pos; +}; + +struct drive +{ + int motor; + int drive; + int ddrw; + int disk_byte; + int volume; + int checksum; + int exor_value; + unsigned char disk_data[258]; + struct diskette disk[2]; +}; + +extern struct drive disk6; + +void c_init_6(); +int c_new_diskette_6(int, char*, int, int, int); +void c_eject_6(int); + +void disk_read_nop(), + disk_read_phase(), + disk_read_motor_off(), + disk_read_motor_on(), + disk_read_select_a(), + disk_read_select_b(), + disk_read_byte(), + disk_read_latch(), + disk_write_latch(), + disk_read_prepare_in(), + disk_read_prepare_out(); + +#define A2_DISK_H +#endif diff --git a/src/display.S b/src/display.S new file mode 100644 index 00000000..dededced --- /dev/null +++ b/src/display.S @@ -0,0 +1,1238 @@ +/* + * Apple // emulator for Linux: + * Functions for low-level framebuffer output. + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#define __ASSEMBLY__ +#include "apple2.h" +#include "video.h" +#include "cpu.h" +#include "misc.h" + +/* ------------------------------------------------------------------------- + Graphics routines. + Care has been taken to isolate the dimension-dependent (320x200 vs 640x400) + routines. + ------------------------------------------------------------------------- */ + +#ifdef _640x400 +#define Font SN(video__wider_font) +#define Font80 SN(video__font) +#else /* !_640x400 */ +#define Font SN(video__font) +#endif /* !_640x400 */ + +/* ------------------------------------------------------------------------- + * Plot exatly 7 pixels from FROM to TO. + * ecx: scratch + * ------------------------------------------------------------------------- */ +#define Plot7Pixels(FROM,TO)\ + movl (FROM), %ecx; /* long -> GM */ \ + movl %ecx, (TO); \ + addl $4, FROM; /* inc pointers */ \ + addl $4, TO; \ + movw (FROM), %cx; /* word -> GM */ \ + movw %cx, (TO); \ + addl $2, FROM; /* inc pointers */ \ + addl $2, TO; \ + movb (FROM), %cl; /* byte -> GM */ \ + movb %cl, (TO); + + +#ifdef _640x400 + +#define LoadHiresTableRef(TABLE)\ + leal SN(video__wider_hires_##TABLE), %ebx;\ + shll $4, %eax;/* *16 */\ + addl %eax, %ebx; + +/* ------------------------------------------------------------------------- + * Plot a normal swath of pixels. + * For 640x400 this is 2 rows of 14 pixels. + * ebx: from table + * eax: to graphics memory + * ------------------------------------------------------------------------- */ +#define PlotPixels\ + PlotPixels640\ + subl $12, %ebx;\ + addl $SCANWIDTH-12, %eax;\ + PlotPixels640\ + subl $SCANWIDTH, %eax;\ + addl $1, %eax; +#define PlotPixels640\ + movl (%ebx), %ecx; /* long -> GM */ \ + movl %ecx, (%eax); \ + addl $4, %eax; /* inc pointers */ \ + addl $4, %ebx; \ + movl (%ebx), %ecx; /* long -> GM */ \ + movl %ecx, (%eax); \ + addl $4, %eax; /* inc pointers */ \ + addl $4, %ebx; \ + movl (%ebx), %ecx; /* long -> GM */ \ + movl %ecx, (%eax); \ + addl $4, %eax; /* inc pointers */ \ + addl $4, %ebx; \ + movw (%ebx), %cx; /* word -> GM */ \ + movw %cx, (%eax); + +/* ------------------------------------------------------------------------- + * Plot a dynamically interpolated swath of pixels. + * For 640x400 this is 2 rows of 18 pixels. + * ebx: from table + * eax: to graphics memory + * ecx: scratch + * ------------------------------------------------------------------------- */ +#define PlotPixelsExtra\ + subl $2, %eax;\ + pushl %edx;\ + xorl %edx, %edx;\ + PlotPixelsExtraRow;\ + addl $SCANWIDTH-18, %eax;\ + subl $9, %ebx;\ + PlotPixelsExtraRow;\ + popl %edx; +#define PlotPixelsExtraRow\ + movb $9, %dl;\ + 1: movb (%ebx), %cl;\ + movb %cl, %ch;\ + movw %cx, (%eax);\ + incl %ebx;\ + addl $2, %eax;\ + decb %dl;\ + jnz 1b; + + +/* ------------------------------------------------------------------------- + * Plot an 80 column character row. We can do this only in 640x400 resolution. + * For 640x400 this is 2 rows of 7 pixels. + * esi: from table + * eax: to graphics memory + * ------------------------------------------------------------------------- */ +#define PlotCharacter80Row\ + Plot7Pixels(%esi,%eax);\ + addl $ SCANWIDTH-6, %eax;/* Go to next row */\ + subl $6, %esi;\ + Plot7Pixels(%esi,%eax);\ + +/* ------------------------------------------------------------------------- + * Plot a 40 column character row. + * For 640x400 this is 2 rows of 14 pixels. + * esi: from table + * eax: to graphics memory + * ------------------------------------------------------------------------- */ +#define PlotCharacter40Row\ + PlotCharacter40Row640\ + subl $12, %esi;\ + addl $ SCANWIDTH-12, %eax;\ + PlotCharacter40Row640\ + addl $2, %esi; +#define PlotCharacter40Row640\ + movl (%esi), %ecx; \ + movl %ecx, (%eax); \ + addl $4, %esi; \ + addl $4, %eax; \ + movl (%esi), %ecx; \ + movl %ecx, (%eax); \ + addl $4, %esi; \ + addl $4, %eax; \ + movl (%esi), %ecx; \ + movl %ecx, (%eax); \ + addl $4, %esi; \ + addl $4, %eax; \ + movw (%esi), %cx; \ + movw %cx, (%eax); + +/* ------------------------------------------------------------------------- + * Plot a 40 column row of lores graphics. + * For 640x400 this is 2 rows of 14 pixels. + * esi: from table + * eax: to graphics memory + * ------------------------------------------------------------------------- */ +#define PlotBlockRow \ + PlotBlockRow640 \ + addl $ SCANWIDTH-12, %eax; \ + PlotBlockRow640 +#define PlotBlockRow640\ + movl %edx, (%eax); \ + addl $4, %eax; \ + movl %edx, (%eax); \ + addl $4, %eax; \ + movl %edx, (%eax); \ + addl $4, %eax; \ + movw %dx, (%eax); + +/* ------------------------------------------------------------------------- + * Get the adjancent color bytes in memory. + * For 640x400 mode, we need to remember to move around by a factor of 2. + * ebx: graphics memory index + * eax: temp buffer for comparison + * ------------------------------------------------------------------------- */ +#define GrabAdjGMBytes\ + subl $3, %ebx;\ + movw (%ebx), %cx;\ + movw %cx, (%eax); /* GM -> temp */\ + addl $9, %eax;\ + addl $18, %ebx;\ + movw (%ebx), %cx;\ + movw %cx, (%eax); /* GM -> temp */\ + decl %eax; + +/* ------------------------------------------------------------------------- + * Plots a normalized byte of dhires color directly into graphics memory. + * eax: graphics memory index + * ebx: dhires_colors index + * edx: scratch + * ------------------------------------------------------------------------- */ +#define PlotDHiresByte\ + movb SN(video__dhires2)(,%ebx,1), %dl;\ + movb %dl, %dh;\ + shll $16, %edx;\ + movb SN(video__dhires1)(,%ebx,1), %dl;\ + movb %dl, %dh;\ + movl %edx, (%eax);\ + movl %edx, SCANWIDTH(%eax);\ + addl $4, %eax; + +#define PlotDHiresFirstByte\ + subl $4, %eax;\ + PlotDHiresByte + +#else /* if ! _640x400 */ + +#define LoadHiresTableRef(TABLE)\ + leal SN(video__hires_##TABLE)(,%eax,8), %ebx; + + +/* ------------------------------------------------------------------------- + * Plot a normal swath of pixels. + * For 320x200 this is exactly 7 pixels. + * ebx: from table + * eax: to graphics memory + * ------------------------------------------------------------------------- */ +#define PlotPixels\ + Plot7Pixels(%ebx,%eax) +#define PlotCharacter40Row \ + Plot7Pixels(%esi,%eax) +#define PlotBlockRow \ + movl %edx, (%eax); \ + addl $4, %eax; \ + movw %dx, (%eax); \ + addl $2, %eax; \ + movb %dl, (%eax); + +/* ------------------------------------------------------------------------- + * Plot a dynamically interpolated swath of pixels + * For 320x200 this is exactly 9 pixels. + * ebx: from table + * eax: to graphics memory + * ecx: scratch + * ------------------------------------------------------------------------- */ +#define PlotPixelsExtra\ + decl %eax;\ + movl (%ebx), %ecx;\ + movl %ecx, (%eax);\ + addl $4, %eax;\ + addl $4, %ebx;\ + movl (%ebx), %ecx;\ + movl %ecx, (%eax);\ + addl $4, %eax;\ + addl $4, %ebx;\ + movb (%ebx), %cl;\ + movb %cl, (%eax); + +/* ------------------------------------------------------------------------- + * Get the adjancent color bytes in memory. + * ebx: graphics memory index + * eax: temp buffer for comparison + * ------------------------------------------------------------------------- */ +#define GrabAdjGMBytes\ + subl $2, %ebx;\ + movw (%ebx), %cx;\ + movw %cx, (%eax); /* GM -> temp */\ + addl $9, %eax;\ + addl $9, %ebx;\ + movw (%ebx), %cx;\ + movw %cx, (%eax); /* GM -> temp */\ + decl %eax; + +/* ------------------------------------------------------------------------- + * Plots a normalized byte of dhires color directly into graphics memory. + * eax: graphics memory index + * ebx: dhires_colors index + * edx: scratch + * ------------------------------------------------------------------------- */ +#define PlotDHiresByte \ + movb SN(video__dhires1)(,%ebx,1), %dl; \ + movb SN(video__dhires2)(,%ebx,1), %dh; \ + movw %dx, (%eax); \ + addl $2, %eax; + +#define PlotDHiresFirstByte\ + subl $2, %eax;\ + PlotDHiresByte + +#endif/*_640x400*/ + + +/* ------------------------------------------------------------------------- + * Calculate the graphics memory offset based on EffectiveAddr. + * BASE 0x2000, 0x4000 + * PTR register to store the offset + * ------------------------------------------------------------------------- */ +#define CalcHiresGM(BASE,PTR,GM)\ + movl EffectiveAddr_E, %ecx; /* ecx = mem addrs */ \ + subw BASE, EffectiveAddr; /* - graphics base */ \ + movl SN(video__screen_addresses) \ + (,EffectiveAddr_E,4), PTR; /* PTR = GM offset */ \ + movl %ecx, EffectiveAddr_E; /* + graphics base */ \ + addl SN(GM), PTR; /* PTR += GM base */ + + +/* ------------------------------------------------------------------------- + * PlotByte - macro to plot a hires byte into graphics memory. + * BASE = 0x2000,0x4000. + * TABLE = expanded_col_hires_even, expanded_col_hires_odd. + * OPP_TABLE = opposite table + * INTERP_COLOR = video__even_colors, video__odd_colors + * ALT_INTERP_COLOR = opposite colors + * ------------------------------------------------------------------------- */ +#define PlotByte(BASE,X,TABLE,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR,GM)\ + pushl %eax; /* save regs */ \ + pushl %ebx; \ + pushl %ecx; \ + \ + xorb %ah, %ah; /* clear noise */ \ + testb $0xFF, SN(video__strictcolors); \ + jnz PB_dynamic##X; /* dynamic color mode */\ + LoadHiresTableRef(TABLE);\ + CalcHiresGM(BASE,%eax,GM); /* eax = GM */\ + PlotPixels; /* temp -> GM */\ + jmp PB_exit##X;\ + \ +PB_dynamic##X:\ + leal SN(video__hires_##TABLE)(,%eax,8), %ebx;\ + leal SN(temp), %eax; /* eax = temp */\ + addl $2, %eax;\ + Plot7Pixels(%ebx,%eax); /* 7bytes -> temp+2 */\ + \ + subl $8, %eax;\ + CalcHiresGM(BASE,%ebx,GM); /* ebx = GM */\ + /* copy adjacent color bytes into temp array */\ + GrabAdjGMBytes;\ + \ + /* calculate dynamic colors in temp array */\ + DynamicCalculateColor(X,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR);\ +PB_plot_dynamic##X:\ + leal SN(temp), %ebx; /* ebx = temp */\ + incl %ebx;\ + CalcHiresGM(BASE,%eax,GM); /* eax = GM */\ + PlotPixelsExtra /* temp -> GM: 1 + 7 + 1 */\ +PB_exit##X:\ + popl %ecx; /* restore regs */ \ + popl %ebx; \ + popl %eax; + + +/* ------------------------------------------------------------------------- + * Dynamic calculation of color at the edges of bytes. + * ------------------------------------------------------------------------- */ +#define DynamicCalculateColor(X,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR);\ + movw (%eax), %cx; \ + testb $0xFF, %ch; /* check right color */ \ + jz PB_next0##X; /* right black, do other end */ \ + movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\ + andb $1, %ch; \ + jz PB_black0##X; /* right black */ \ + andb $0x40, %cl; \ + jz PB_black0##X; /* inside black, right colored */ \ + movw $0x3737, (%eax); /* edge is white (#55) */ \ + jmp PB_next0##X; \ +PB_black0##X: \ + movzwl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\ + movb %ch, %cl; \ + xorb %ch, %ch; \ + leal SN(video__hires_##OPP_TABLE) \ + (,%ecx,8), %ebx; \ + incl %eax; \ + movb (%ebx), %cl; \ + movb %cl, (%eax); \ + decl %eax; \ +PB_next0##X: \ + decw EffectiveAddr; /* previous byte */ \ + subl $7, %eax; /* left edge of byte */ \ + movb (%eax), %cl; \ + testb $0xFF, %cl; /* check left color */ \ + jz PB_next1##X; /* left black, done */ \ + movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\ + andb $0x40, %cl; \ + jz PB_black1##X; /* left black */ \ + andb $0x1, %ch; \ + jz PB_black1##X; /* left colored, inside black */ \ + movw $0x3737, (%eax); /* edge is white (#55) */ \ + jmp PB_next1##X; \ +PB_black1##X: \ + movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\ + leal SN(video__hires_##OPP_TABLE) \ + (,%ecx,8), %ebx; \ + addl $6, %ebx; \ + movb (%ebx), %cl; \ + movb %cl, (%eax); \ +PB_next1##X: \ + incw EffectiveAddr; \ + /* do extra calculation for interpolated colors */ \ + cmpb $2, SN(video__strictcolors); \ + jne PB_plot_dynamic##X; \ + \ + decw EffectiveAddr; \ + CalculateInterpColor(X,2,ALT_INTERP_COLOR); \ +PB_next2##X: \ + incw EffectiveAddr; \ + incl %eax; \ + CalculateInterpColor(X,3,INTERP_COLOR); \ +PB_next3##X: \ + addl $6, %eax; \ + CalculateInterpColor(X,4,INTERP_COLOR); \ +PB_next4##X: \ + incw EffectiveAddr; \ + incl %eax; \ + CalculateInterpColor(X,5,ALT_INTERP_COLOR); \ +PB_next5##X: \ + decw EffectiveAddr; + + +/* ------------------------------------------------------------------------- + * Calculates the color at the edge of interpolated bytes. + * Done 4 times in little endian order (...7 0...7 0...) + * ------------------------------------------------------------------------- */ +#define CalculateInterpColor(X,Y,INTERP_COLOR) \ + testb $0xFF, (%eax); \ + jnz PB_next##Y##X; /* not black, next */ \ + movw (%eax), %cx; /* off+1 in %ch */ \ + testb $0xFF, %ch; \ + jz PB_next##Y##X; /* off+1 is black, next */ \ + movb -1(%eax), %cl; /* off-1 in %cl */ \ + testb $0xFF, %cl; \ + jz PB_next##Y##X; /* off-1 is black, next */ \ + cmpb $55, %cl; /* off-1 is white? */ \ + je PB_white0##X##Y; \ + movb %cl, (%eax); /* store non-white */ \ + jmp PB_next##Y##X; /* next */ \ +PB_white0##X##Y: \ + cmpb $55, %ch; /* off+1 is white? */ \ + je PB_white##X##Y; \ + movb %ch, (%eax); /* store non-white */ \ + jmp PB_next##Y##X; /* next */ \ +PB_white##X##Y: /* both sides are white */ \ + movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\ + shrb $7, %cl; \ + movb SN(INTERP_COLOR)(,%ecx,1), %bl; \ + movb %bl, (%eax); + + +/* ------------------------------------------------------------------------- + * compeletely update all the hires/dhires page rows. + * X=0,1 + * OFFSET=0x2027,0x4027 (page 1, 2) + * ------------------------------------------------------------------------- */ +#define UpdateHiresRows(PRE,X,OFFSET) \ +update_hires_rows_##X: \ + movl $20, %ecx; /* ECX: 40 column counter */ \ + movl %ebx, %edx; /* EBX: pixel row counter */ \ + shrb $3, %dl; /* normalize to 0 - 23 */ \ + /* EDI: row offset */ \ + movw SN(video__line_offset)(,%edx,2), \ + EffectiveAddr; \ + movl %ebx, %edx; \ + andb $0x7, %dl; \ + shlw $10, %dx; /* EDX: offset range 0 - 1C00 */ \ + addw OFFSET, %dx; /* add base end-row offset */ \ + addw %dx, EffectiveAddr; /* EDI: mem address */ \ +update_hires_columns_##X: \ + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\ + cmpw $159, %bx; /* mixed mode boundary */ \ + jg update_hires_mixed_##X; \ + call SN(PRE##odd##X##); \ + decw EffectiveAddr; /* previous address */ \ + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\ + call SN(PRE##even##X##); \ + jmp update_hires_cont_##X; \ +update_hires_mixed_##X: \ + call SN(PRE##odd##X##_mixed); \ + decw EffectiveAddr; /* previous address */ \ + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\ + call SN(PRE##even##X##_mixed); \ +update_hires_cont_##X: \ + decw EffectiveAddr; /* previous address */ \ + decb %cl; /* dec column counter */ \ + jnz update_hires_columns_##X; \ + decw %bx; /* dec row */ \ + jns update_hires_rows_##X; + + +/* ------------------------------------------------------------------------- + * compeletely update all the text page rows. + * X=0,1 + * OFF=0x427,0x827 (page 1, 2) + * ------------------------------------------------------------------------- */ +#define UpdateRows(PRE,X,OFFSET) \ +update_rows_##X: \ + movl $39, %ecx; \ + movw SN(video__line_offset)(,%ebx,2), \ + EffectiveAddr; \ + addw OFFSET, EffectiveAddr; \ +update_columns_##X: \ + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al;\ + cmpb $19, %bl; \ + jg update_mixed_##X; \ + call SN(PRE##text##X); \ + jmp update_cont_##X; \ +update_mixed_##X: \ + call SN(PRE##text##X##_mixed); \ +update_cont_##X: \ + decw %di; \ + decb %cl; \ + jns update_columns_##X; \ + decb %bl; \ + jns update_rows_##X; + + +/* ------------------------------------------------------------------------- + * Plot a full double hires color byte into GM + * OFF 0x2000, 0x4000 + * PROBLEMS: + * graphics artifiacts are not implemented correctly. + * ------------------------------------------------------------------------- */ +#define PlotDHires(OFF,X,GM) \ + pushl %eax; /* save regs */ \ + pushl %ebx; \ + pushl %ecx; \ + pushl %edx; \ + pushl EffectiveAddr_E; \ + \ + andw $0xFFFF, EffectiveAddr; /* erase offset */ \ + btr $0, EffectiveAddr_E; /* normalize */ \ + movl EffectiveAddr_E, %ecx; /* ecx = mem addrs */ \ + subw OFF, EffectiveAddr; /* - graphics base */ \ + movl SN(video__screen_addresses) \ + (,EffectiveAddr_E,4), %eax; /* eax = GM offset */ \ + movb SN(video__columns) \ + (,EffectiveAddr_E,1), %bl; \ + addl SN(GM), %eax; /* eax += GM base */ \ + \ + leal SN(apple_ii_64k), EffectiveAddr_E;\ + addl %ecx, EffectiveAddr_E; \ + movl EffectiveAddr_E, %ecx; \ + addl $BANK2, %ecx; \ + \ + testb $0xFF, %bl; \ + jz plot_dhires##X##_cont; \ + movzbl -1(EffectiveAddr_E), %ebx; \ + movb 0(%ecx), %bh; \ + btr $7, %ebx; \ + shrb $3, %bl; \ + shlb $4, %bh; \ + orb %bh, %bl; \ + xorb %bh, %bh; \ + PlotDHiresFirstByte \ + \ +plot_dhires##X##_cont: \ + movl %ecx, %edx; \ + movb 2(%edx), %cl; \ + shll $28, %ecx; \ + \ + movzbl 1(EffectiveAddr_E), %ebx; \ + btr $7, %ebx; /* erase msb */ \ + shll $21, %ebx; \ + orl %ebx, %ecx; \ + \ + movzbl 1(%edx), %ebx; \ + btr $7, %ebx; /* erase msb */ \ + shll $14, %ebx; \ + orl %ebx, %ecx; \ + \ + movzbl 0(EffectiveAddr_E), %ebx; \ + btr $7, %ebx; /* erase msb */ \ + shll $7, %ebx; \ + orl %ebx, %ecx; \ + \ + movzbl 0(%edx), %ebx; \ + btr $7, %ebx; /* erase msb */ \ + orl %ebx, %ecx; \ + /* 00000001 11111122 22222333 3333xxxx */ \ + \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + shrl $4, %ecx; \ + movb %cl, %bl; \ + PlotDHiresByte \ + popl EffectiveAddr_E; \ + andl $0xFFFF, EffectiveAddr_E;/* for safety */ \ + popl %edx; \ + popl %ecx; /* restore regs */ \ + popl %ebx; \ + popl %eax; \ + ret; + + +/* ------------------------------------------------------------------------- + * setup to plot the text/lores stuff. + * eax: graphics memory pointer + * ------------------------------------------------------------------------- */ +#define PlotTextPagePre(OFF,GM,PAGE)\ + pushal; /*Save everything -MUST BE MATCHED!*/\ + xorb %ah, %ah;\ + movl %eax, %esi; /*ESI=EAX=Chr code*/\ + subw OFF, EffectiveAddr; /*Normalize scrn addr*/\ + /*Compute row*/\ + movl SN(video__screen_addresses)(,EffectiveAddr_E,4), %eax;\ + addl SN(GM), %eax; /*Graphic addr*/ + + +/* ------------------------------------------------------------------------- + * Common code for plotting an 80 column character. + * Only 640x400 resolution can do this. + * eax: graphics memory pointer + * esi: precalculated font pointer + * OFF 0x400, 0x800 + * PAGE 0, 1 + * ------------------------------------------------------------------------- */ +#define Plot80Character(TAG,OFF,GM,PAGE)\ + PlotTextPagePre(OFF,GM,PAGE)/* does a pushal */\ +plot_80character_correct_page##TAG:\ + addw %bx, %ax; /*screen offset*/\ + shll $6, %esi; /* * 64 = 8cols * 8rows*/\ + addl $ Font80, %esi; /*Font addr*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + addl $2, %esi;\ + addl $ SCANWIDTH-6, %eax; /*Go to next row*/\ + \ + PlotCharacter80Row;\ + \ + popal; /* MATCHES pushal from PlotTextPagePre */ + + + + /* ----------------------------------------------------------------- + * Scan through video memory (text & graphics) and call the updating + * routines. Depending on softswitch settings, either text or + * graphics, page 1 or 2 will be rendered. + * This is called on exit from menu screens, etc. + * ebx: number of rows (counting down) + * ----------------------------------------------------------------- */ +E(video_redraw) + pushal + + /* Temporarily reset some softswitches. This ensures a + * proper update in the case where the video addresses + * are pointed at auxillary memory, yet a non-80col mode is + * in use. + */ + pushl SN(softswitches) + andl $~(SS_TEXTWRT|SS_HGRWRT|SS_RAMWRT),SN(softswitches) + + xorl %eax, %eax + xorl %edi, %edi + + /* 24 rows text/lores page 0 */ + movl $23, %ebx +#ifdef APPLE_IIE + UpdateRows(iie_soft_write_,0,$0x427) +#else + UpdateRows(video__write_,0,$0x427) +#endif + + /* 24 rows text/lores page 1 */ + movl $23, %ebx +#ifdef APPLE_IIE + UpdateRows(iie_soft_write_,1,$0x827) +#else + UpdateRows(video__write_,1,$0x827) +#endif + + /* 192 rows hires page 0 */ + movl $191, %ebx +#ifdef APPLE_IIE + UpdateHiresRows(iie_soft_write_,0,$0x2027) +#else + UpdateHiresRows(video__write_,0,$0x2027) +#endif + + /* 192 rows hires page 1 */ + movl $191, %ebx +#ifdef APPLE_IIE + UpdateHiresRows(iie_soft_write_,1,$0x4027) +#else + UpdateHiresRows(video__write_,1,$0x4027) +#endif + + popl SN(softswitches) + popal + ret + + /******************************************/ + +E(video__write_text0) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz plot_character0 + testl $SS_HIRES, SN(softswitches) # lores mode? + jz plot_block0 + ret + +E(video__write_text0_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + # Text or mixed mode? + jnz plot_character0 + testl $SS_HIRES, SN(softswitches) # Not hires mode? + jz plot_block0 + ret + +E(video__write_text1) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) + jnz plot_character1 + testl $SS_HIRES, SN(softswitches) # lores mode? + jz plot_block1 + ret + +E(video__write_text1_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + # Text or mixed mode? + jnz plot_character1 + testl $SS_HIRES, SN(softswitches) # Not hires mode? + jz plot_block1 + ret + +#ifdef APPLE_IIE +/* video__write_2e_text0 - handle text page //e specific */ +E(video__write_2e_text0) + addl SN(base_textwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_textwrt), EffectiveAddr_E +iie_soft_write_text0: + testl $SS_TEXT, SN(softswitches) # Text mode? + jz iie_write_lores0 # graphics + testl $SS_80COL, SN(softswitches) + jnz plot_80character0 # 80 col text + testl $SS_TEXTWRT, SN(softswitches) + jnz ram_nop # NOP (in auxram) + jmp plot_character0 # 40 col text + +iie_write_lores0: + testl $(SS_HIRES|SS_TEXTWRT), SN(softswitches) + jz plot_block0 # lores & 80col + ret + +/* video__write_2e_text0_mixed - handle mixed text page //e specific */ +E(video__write_2e_text0_mixed) + addl SN(base_textwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_textwrt), EffectiveAddr_E +iie_soft_write_text0_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jz iie_write_lores0 + testl $SS_80COL, SN(softswitches) + jnz plot_80character0 + testl $SS_TEXTWRT, SN(softswitches) + jnz ram_nop # NOP (in auxram) + jmp plot_character0 # 40 col text + +/* video__write_2e_text1 - handle text page1 //e specific */ +E(video__write_2e_text1) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_text1: + testl $SS_TEXT, SN(softswitches) # Text mode? + jz iie_write_lores1 # graphics + testl $SS_80COL, SN(softswitches) + jnz plot_80character1 # 80 col text + testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # NOP (in auxram) + jmp plot_character1 # 40 col text + +iie_write_lores1: + testl $(SS_HIRES|SS_RAMWRT), SN(softswitches) + jz plot_block1 # lores & main bank + ret + + +/* video__write_2e_text1_mixed - handle mixed page 1 //e specific */ +E(video__write_2e_text1_mixed) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_text1_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jz iie_write_lores1 + testl $SS_80COL, SN(softswitches) + jnz plot_80character1 + testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # NOP (in auxram) + jmp plot_character1 # 40 col text + +#endif /* APPLE_IIE */ + +E(video__write_even0) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_even_byte0 + ret + +E(video__write_even0_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # Text/mixed mode? + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_even_byte0 + ret + +E(video__write_odd0) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_odd_byte0 + ret + +E(video__write_odd0_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # Text/mixed mode? + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_odd_byte0 + ret + +#ifdef APPLE_IIE +/* video__write_2e_even0 - handle hires page //e specific */ +E(video__write_2e_even0) + addl SN(base_hgrwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_hgrwrt), EffectiveAddr_E +iie_soft_write_even0: + testl $SS_TEXT, SN(softswitches) + jnz ram_nop # text + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires0 # dhires +1: testl $SS_HGRWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_even_byte0 # plot hires + + +/* video__write_2e_even0_mixed - handle mixed hires page //e specific */ +E(video__write_2e_even0_mixed) + addl SN(base_hgrwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_hgrwrt), EffectiveAddr_E +iie_soft_write_even0_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # text/mix + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires0 # dhires +1: testl $SS_HGRWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_even_byte0 # plot hires + +/* video__write_2e_odd0 - handle hires page //e specific */ +E(video__write_2e_odd0) + addl SN(base_hgrwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_hgrwrt), EffectiveAddr_E +iie_soft_write_odd0: + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop # text + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires0 # dhires +1: testl $SS_HGRWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_odd_byte0 # plot hires + +/* video__write_2e_odd0_mixed - handle mixed hires page //e specific */ +E(video__write_2e_odd0_mixed) + addl SN(base_hgrwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_hgrwrt), EffectiveAddr_E +iie_soft_write_odd0_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # text/mix + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches) # dhires mode? + jnz iie_plot_dhires0 # dhires +1: testl $SS_HGRWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_odd_byte0 # plot hires +#endif + +E(video__write_even1) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_even_byte1 + ret + +E(video__write_even1_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT|SS_MIXED, SN(softswitches) + jnz ram_nop # text/mixed + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_even_byte1 + ret + +E(video__write_odd1) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_odd_byte1 + ret + +E(video__write_odd1_mixed) + movb %al, SN(apple_ii_64k)(,EffectiveAddr_E,1) + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # text/mixed + testl $SS_HIRES, SN(softswitches) # hires mode? + jnz plot_odd_byte1 + ret + +#ifdef APPLE_IIE +/* video__write_2e_even1 - write hires page1 //e specific */ +E(video__write_2e_even1) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_even1: + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop # text + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches) # dhires mode? + jnz iie_plot_dhires1 # dhires +1: testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_even_byte1 # plot hires + +/* video__write_2e_even1_mixed - write hires page1 //e specific */ +E(video__write_2e_even1_mixed) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_even1_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # text/mix + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires1 # dhires +1: testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_even_byte1 # plot hires + +/* video__write_2e_odd1 - write hires page1 //e specific */ +E(video__write_2e_odd1) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_odd1: + testl $SS_TEXT, SN(softswitches) # Text mode? + jnz ram_nop # text + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires1 # dhires +1: testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # in auxram +_iie_plot_hires_page1_odd: + jmp plot_odd_byte1 # plot hires + +/* video__write_2e_odd1_mixed - write hires page1 //e specific */ +E(video__write_2e_odd1_mixed) + addl SN(base_ramwrt), EffectiveAddr_E + movb %al, (EffectiveAddr_E) + subl SN(base_ramwrt), EffectiveAddr_E +iie_soft_write_odd1_mixed: + testl $(SS_TEXT|SS_MIXED), SN(softswitches) + jnz ram_nop # text/mix + testl $SS_HIRES, SN(softswitches) # hires mode? + jz ram_nop # lores + testl $SS_80COL, SN(softswitches) + jz 1f # not dhires + testl $SS_DHIRES, SN(softswitches)# dhires mode? + jnz iie_plot_dhires1 # dhires +1: testl $SS_RAMWRT, SN(softswitches) + jnz ram_nop # in auxram + jmp plot_odd_byte1 # plot hires + + .align 4 +iie_plot_dhires0: + PlotDHires($0x2000,0,video__fb1) + ret + +iie_plot_dhires1: + PlotDHires($0x4000,1,video__fb2) + ret + + +#ifdef _640x400 + .align 4 +plot_80character0: + pushl %ebx + pushl EffectiveAddr_E + + orl $0x10000, EffectiveAddr_E # aux ram + movl $0, %ebx # +0 screen offset + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + andl $0xFFFF, EffectiveAddr_E + Plot80Character(0a,$0x400,video__fb1,$0) + + popl EffectiveAddr_E # main ram + movl $7, %ebx # +7 screen offset + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + Plot80Character(0b,$0x400,video__fb1,$0) + + popl %ebx + ret + + .align 4 +plot_80character1: + pushl %ebx + pushl EffectiveAddr_E + + orl $0x10000, EffectiveAddr_E # aux ram + movl $0, %ebx # +0 screen offset + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + andl $0xFFFF, EffectiveAddr_E + Plot80Character(1a,$0x800,video__fb2,$1) + + popl EffectiveAddr_E # main ram + movl $7, %ebx # +7 screen offset + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + Plot80Character(1b,$0x800,video__fb2,$1) + + popl %ebx + ret + +#else /* !640x400 resolution is not sufficient for 80 column */ + .align 4 +plot_80character0: + andl $0xFFFF, EffectiveAddr_E/* for safety */ + ret + + .align 4 +plot_80character1: + andl $0xFFFF, EffectiveAddr_E/* for safety */ + ret +#endif /* _640x400 */ + +#endif /* APPLE_IIE */ + + +/* plot character on first text page */ + .align 4 +plot_character0: + PlotTextPagePre($0x400,video__fb1,$0) +plot_character_correct_page: +#ifdef _640x400 + shll $7, %esi # * 128 +#else + shll $6, %esi # * 64 +#endif + addl $ Font, %esi # Font addr + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + addl $2, %esi; + addl $ SCANSTEP, %eax # Go to next row + + PlotCharacter40Row + + popal + ret + + +/* plot character on second text page */ + .align 4 +plot_character1: + PlotTextPagePre($0x800,video__fb2,$1) + jmp plot_character_correct_page # same as page 0 + + +/* plot lores block first page */ + +plot_block0: + PlotTextPagePre($0x400,video__fb1,$0) +plot_block_correct_page: + movw %si, %dx # Compute color + andb $0x0F, %dl + shlb $4, %dl + movb %dl, %dh + shll $16, %edx + movw %si, %dx + andb $0x0F, %dl + shlb $4, %dl + movb %dl, %dh + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + movw %si, %dx # Compute color + andb $0xF0, %dl + movb %dl, %dh + shll $16, %edx + movw %si, %dx + andb $0xF0, %dl + movb %dl, %dh + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + addl $ SCANSTEP, %eax # Go to next row + + PlotBlockRow + + popal + ret + + .align 4 +plot_block1: + PlotTextPagePre($0x800,video__fb2,$1) + jmp plot_block_correct_page + + + +/* plot even column hires byte on page 0 */ + .align 4 +plot_even_byte0: + PlotByte($0x2000,0,even,odd,video__even_colors,video__odd_colors,video__fb1) + ret + +/* plot odd column hires byte on page 0 */ + .align 4 +plot_odd_byte0: + PlotByte($0x2000,1,odd,even,video__odd_colors,video__even_colors,video__fb1) + ret + +/* plot even column hires byte on page 1 */ + .align 4 +plot_even_byte1: + PlotByte($0x4000,2,even,odd,video__even_colors,video__odd_colors,video__fb2) + ret + +/* plot odd column hires byte on page 1 */ + .align 4 +plot_odd_byte1: + PlotByte($0x4000,3,odd,even,video__odd_colors,video__even_colors,video__fb2) + ret + diff --git a/src/font.txt b/src/font.txt new file mode 100644 index 00000000..7ca28d85 --- /dev/null +++ b/src/font.txt @@ -0,0 +1,1276 @@ +; Font master file +; +; This file gives the font used for the Apple Text modes and interface +; screens. Inverse and Flashing characters are generated within the program +; +; "ucase_glyphs" contains the ASCII glyphs 64--95 (mostly uppercase +; letters), followed by 32--63 (numbers and punctuation). Although backwards +; this is most convienent for generating the Apple character set. +; +; "lcase_glyphs" contains the remaining ASCII glyphs 96-128, mostly lowercase +; letters. +; +; "mousetext_glyphs" contains the Enhanced //e MouseText glyphs +; +; "interface_glyphs" contains extra chars used for the control menus, +; presently just box-drawing. +; +; Arranged by Michael Deutschmann +; (the font itself presumably originated with Apple, but bitmap fonts are not +; copyrightable.) +; += ucase_glyphs,64 +: 0x00 +..###.. +.#...#. +.#.#.#. +.#.###. +.#.##.. +.#..... +..####. +....... +: 0x01 +...#... +..#.#.. +.#...#. +.#...#. +.#####. +.#...#. +.#...#. +....... +: 0x02 +.####.. +.#...#. +.#...#. +.####.. +.#...#. +.#...#. +.####.. +....... +: 0x03 +..###.. +.#...#. +.#..... +.#..... +.#..... +.#...#. +..###.. +....... +: 0x04 +.####.. +.#...#. +.#...#. +.#...#. +.#...#. +.#...#. +.####.. +....... +: 0x05 +.#####. +.#..... +.#..... +.####.. +.#..... +.#..... +.#####. +....... +: 0x06 +.#####. +.#..... +.#..... +.####.. +.#..... +.#..... +.#..... +....... +: 0x07 +..####. +.#..... +.#..... +.#..... +.#..##. +.#...#. +..####. +....... +: 0x08 +.#...#. +.#...#. +.#...#. +.#####. +.#...#. +.#...#. +.#...#. +....... +: 0x09 +..###.. +...#... +...#... +...#... +...#... +...#... +..###.. +....... +: 0x0a +.....#. +.....#. +.....#. +.....#. +.....#. +.#...#. +..###.. +....... +: 0x0b +.#...#. +.#..#.. +.#.#... +.##.... +.#.#... +.#..#.. +.#...#. +....... +: 0x0c +.#..... +.#..... +.#..... +.#..... +.#..... +.#..... +.#####. +....... +: 0x0d +.#...#. +.##.##. +.#.#.#. +.#.#.#. +.#...#. +.#...#. +.#...#. +....... +: 0x0e +.#...#. +.#...#. +.##..#. +.#.#.#. +.#..##. +.#...#. +.#...#. +....... +: 0x0f +..###.. +.#...#. +.#...#. +.#...#. +.#...#. +.#...#. +..###.. +....... +: 0x10 +.####.. +.#...#. +.#...#. +.####.. +.#..... +.#..... +.#..... +....... +: 0x11 +..###.. +.#...#. +.#...#. +.#...#. +.#.#.#. +.#..#.. +..##.#. +....... +: 0x12 +.####.. +.#...#. +.#...#. +.####.. +.#.#... +.#..#.. +.#...#. +....... +: 0x13 +..###.. +.#...#. +.#..... +..###.. +.....#. +.#...#. +..###.. +....... +: 0x14 +.#####. +...#... +...#... +...#... +...#... +...#... +...#... +....... +: 0x15 +.#...#. +.#...#. +.#...#. +.#...#. +.#...#. +.#...#. +..###.. +....... +: 0x16 +.#...#. +.#...#. +.#...#. +.#...#. +.#...#. +..#.#.. +...#... +....... +: 0x17 +.#...#. +.#...#. +.#...#. +.#.#.#. +.#.#.#. +.##.##. +.#...#. +....... +: 0x18 +.#...#. +.#...#. +..#.#.. +...#... +..#.#.. +.#...#. +.#...#. +....... +: 0x19 +.#...#. +.#...#. +..#.#.. +...#... +...#... +...#... +...#... +....... +: 0x1a +.#####. +.....#. +....#.. +...#... +..#.... +.#..... +.#####. +....... +: 0x1b +.#####. +.##.... +.##.... +.##.... +.##.... +.##.... +.#####. +....... +: 0x1c +....... +.#..... +..#.... +...#... +....#.. +.....#. +....... +....... +: 0x1d +.#####. +....##. +....##. +....##. +....##. +....##. +.#####. +....... +: 0x1e +....... +....... +...#... +..#.#.. +.#...#. +....... +....... +....... +: 0x1f +....... +....... +....... +....... +....... +....... +.#####. +....... +: 0x20 +....... +....... +....... +....... +....... +....... +....... +....... +: 0x21 +...#... +...#... +...#... +...#... +...#... +....... +...#... +....... +: 0x22 +..#.#.. +..#.#.. +..#.#.. +....... +....... +....... +....... +....... +: 0x23 +..#.#.. +..#.#.. +.#####. +..#.#.. +.#####. +..#.#.. +..#.#.. +....... +: 0x24 +...#... +..####. +.#.#... +..###.. +...#.#. +.####.. +...#... +....... +: 0x25 +.##.... +.##..#. +....#.. +...#... +..#.... +.#..##. +....##. +....... +: 0x26 +..#.... +.#.#... +.#.#... +..#.... +.#.#.#. +.#..#.. +..##.#. +....... +: 0x27 +...#... +...#... +...#... +....... +....... +....... +....... +....... +: 0x28 +...#... +..#.... +.#..... +.#..... +.#..... +..#.... +...#... +....... +: 0x29 +...#... +....#.. +.....#. +.....#. +.....#. +....#.. +...#... +....... +: 0x2a +...#... +.#.#.#. +..###.. +...#... +..###.. +.#.#.#. +...#... +....... +: 0x2b +....... +...#... +...#... +.#####. +...#... +...#... +....... +....... +: 0x2c +....... +....... +....... +....... +...#... +...#... +..#.... +....... +: 0x2d +....... +....... +....... +.#####. +....... +....... +....... +....... +: 0x2e +....... +....... +....... +....... +....... +....... +...#... +....... +: 0x2f +....... +.....#. +....#.. +...#... +..#.... +.#..... +....... +....... +: 0x30 +..###.. +.#...#. +.#..##. +.#.#.#. +.##..#. +.#...#. +..###.. +....... +: 0x31 +...#... +..##... +...#... +...#... +...#... +...#... +..###.. +....... +: 0x32 +..###.. +.#...#. +.....#. +...##.. +..#.... +.#..... +.#####. +....... +: 0x33 +.#####. +.....#. +....#.. +...##.. +.....#. +.#...#. +..###.. +....... +: 0x34 +....#.. +...##.. +..#.#.. +.#..#.. +.#####. +....#.. +....#.. +....... +: 0x35 +.#####. +.#..... +.####.. +.....#. +.....#. +.#...#. +..###.. +....... +: 0x36 +...###. +..#.... +.#..... +.####.. +.#...#. +.#...#. +..###.. +....... +: 0x37 +.#####. +.....#. +....#.. +...#... +..#.... +..#.... +..#.... +....... +: 0x38 +..###.. +.#...#. +.#...#. +..###.. +.#...#. +.#...#. +..###.. +....... +: 0x39 +..###.. +.#...#. +.#...#. +..####. +.....#. +....#.. +.###... +....... +: 0x3a +....... +....... +...#... +....... +...#... +....... +....... +....... +: 0x3b +....... +....... +...#... +....... +...#... +...#... +..#.... +....... +: 0x3c +....#.. +...#... +..#.... +.#..... +..#.... +...#... +....#.. +....... +: 0x3d +....... +....... +.#####. +....... +.#####. +....... +....... +....... +: 0x3e +..#.... +...#... +....#.. +.....#. +....#.. +...#... +..#.... +....... +: 0x3f +..###.. +.#...#. +....#.. +...#... +...#... +....... +...#... +....... += lcase_glyphs,32 +: 0x60 +.#..... +..#.... +...#... +....... +....... +....... +....... +....... +: 0x61 +....... +....... +..###.. +.....#. +..####. +.#...#. +..####. +....... +: 0x62 +.#..... +.#..... +.####.. +.#...#. +.#...#. +.#...#. +.####.. +....... +: 0x63 +....... +....... +..####. +.#..... +.#..... +.#..... +..####. +....... +: 0x64 +.....#. +.....#. +..####. +.#...#. +.#...#. +.#...#. +..####. +....... +: 0x65 +....... +....... +..###.. +.#...#. +.#####. +.#..... +..####. +....... +: 0x66 +...##.. +..#..#. +..#.... +.###... +..#.... +..#.... +..#.... +....... +: 0x67 +....... +....... +..###.. +.#...#. +.#...#. +..####. +.....#. +..###.. +: 0x68 +.#..... +.#..... +.####.. +.#...#. +.#...#. +.#...#. +.#...#. +....... +: 0x69 +...#... +....... +..##... +...#... +...#... +...#... +..###.. +....... +: 0x6a +....#.. +....... +...##.. +....#.. +....#.. +....#.. +.#..#.. +..##... +: 0x6b +.#..... +.#..... +.#...#. +.#..#.. +.###... +.#..#.. +.#...#. +....... +: 0x6c +..##... +...#... +...#... +...#... +...#... +...#... +..###.. +....... +: 0x6d +....... +....... +.##.#.. +.#.#.#. +.#.#.#. +.#.#.#. +.#.#.#. +....... +: 0x6e +....... +....... +.####.. +.#...#. +.#...#. +.#...#. +.#...#. +....... +: 0x6f +....... +....... +..###.. +.#...#. +.#...#. +.#...#. +..###.. +....... +: 0x70 +....... +....... +.####.. +.#...#. +.#...#. +.####.. +.#..... +.#..... +: 0x71 +....... +....... +..####. +.#...#. +.#...#. +..####. +.....#. +.....#. +: 0x72 +....... +....... +.#.###. +.##.... +.#..... +.#..... +.#..... +....... +: 0x73 +....... +....... +..####. +.#..... +..###.. +.....#. +.####.. +....... +: 0x74 +..#.... +..#.... +.#####. +..#.... +..#.... +..#..#. +...##.. +....... +: 0x75 +....... +....... +.#...#. +.#...#. +.#...#. +.#..##. +..##.#. +....... +: 0x76 +....... +....... +.#...#. +.#...#. +.#...#. +..#.#.. +...#... +....... +: 0x77 +....... +....... +.#...#. +.#.#.#. +.#.#.#. +.#.#.#. +..#.#.. +....... +: 0x78 +....... +....... +.#...#. +..#.#.. +...#... +..#.#.. +.#...#. +....... +: 0x79 +....... +....... +.#...#. +.#...#. +.#...#. +..####. +.....#. +..###.. +: 0x7a +....... +....... +.#####. +....#.. +...#... +..#.... +.#####. +....... +: 0x7b +...###. +..##... +..##... +.##.... +..##... +..##... +...###. +....... +: 0x7c +...#... +...#... +...#... +....... +...#... +...#... +...#... +....... +: 0x7d +.###... +...##.. +...##.. +....##. +...##.. +...##.. +.###... +....... +: 0x7e +..##.#. +.#.##.. +....... +....... +....... +....... +....... +....... +: 0x7f +....... +.#.#.#. +..#.#.. +.#.#.#. +..#.#.. +.#.#.#. +....... +....... += mousetext_glyphs,32 +: 0x00 +....#.. +...#... +.##.##. +####### +######. +######. +.###### +.##.##. +: 0x01 +....#.. +...#... +.##.##. +#.....# +#....#. +#....#. +.#.#..# +.##.##. +: 0x02 +....... +....... +.#..... +.##.... +.###... +.####.. +.##.##. +.#....# +: 0x03 +####### +.#...#. +..#.#.. +...#... +...#... +..#.#.. +.#...#. +####### +: 0x04 +....... +......# +.....#. +#...#.. +.#.#... +..#.... +..#.... +....... +: 0x05 +####### +######. +#####.# +.###.## +#.#.### +##.#### +##.#### +####### +: 0x06 +....### +.....## +.###### +#...##. +#..#### +....##. +######. +.#..... +: 0x07 +....... +...##.. +###.... +....... +###.... +..##... +...#... +....### +: 0x08 +...#... +..#.... +.#..... +####### +.#..... +..#.... +...#... +....... +: 0x09 +....... +....... +....... +....... +....... +....... +....... +.#.#.#. +: 0x0a +...#... +...#... +...#... +...#... +#..#..# +.#.#.#. +..###.. +...#... +: 0x0b +...#... +..###.. +.#.#.#. +#..#..# +...#... +...#... +...#... +...#... +: 0x0c +####### +....... +....... +....... +....... +....... +....... +....... +: 0x0d +......# +......# +......# +..#...# +.##...# +####### +.##.... +..#.... +: 0x0e +######. +######. +######. +######. +######. +######. +######. +######. +: 0x0f +##..#.. +...##.. +..###.. +.###### +..###.. +...##.. +....#.. +####.## +: 0x10 +..#..## +..##... +..###.. +######. +..###.. +..##... +..#.... +##.#### +: 0x11 +......# +...#..# +...#... +####### +.#####. +..###.. +...#..# +......# +: 0x12 +......# +...#..# +..###.. +.#####. +####### +...#... +...#..# +......# +: 0x13 +....... +....... +....... +####### +....... +....... +....... +....... +: 0x14 +#...... +#...... +#...... +#...... +#...... +#...... +#...... +####### +: 0x15 +...#... +....#.. +.....#. +####### +.....#. +....#.. +...#... +....... +: 0x16 +.#.#.#. +#.#.#.# +.#.#.#. +#.#.#.# +.#.#.#. +#.#.#.# +.#.#.#. +#.#.#.# +: 0x17 +#.#.#.# +.#.#.#. +#.#.#.# +.#.#.#. +#.#.#.# +.#.#.#. +#.#.#.# +.#.#.#. +: 0x18 +....... +.#####. +#.....# +#...... +#...... +#...... +####### +....... +: 0x19 +....... +....... +######. +......# +......# +......# +####### +....... +: 0x1a +......# +......# +......# +......# +......# +......# +......# +......# +: 0x1b +...#... +..###.. +.#####. +####### +.#####. +..###.. +...#... +....... +: 0x1c +####### +....... +....... +....... +....... +....... +....... +####### +: 0x1d +..#.#.. +..#.#.. +###.### +....... +###.### +..#.#.. +..#.#.. +....... +: 0x1e +####### +......# +......# +..##..# +..##..# +......# +......# +####### +: 0x1f +#...... +#...... +#...... +#...... +#...... +#...... +#...... +#...... +=interface_glyphs,11 +: 0 +....... +....... +....... +....... +...#### +...#... +...#... +...#... +: 1 +....... +....... +....... +....... +####... +...#... +...#... +...#... +: 2 +...#... +...#... +...#... +...#... +...#### +....... +....... +....... +: 3 +...#... +...#... +...#... +...#... +####... +....... +....... +....... +: 4 +...#... +...#... +...#... +...#... +...#... +...#... +...#... +...#... +: 5 +....... +....... +....... +....... +####### +....... +....... +....... +: 6 +...#... +...#... +...#... +...#... +...#### +...#... +...#... +...#... +: 7 +...#... +...#... +...#... +...#... +####... +...#... +...#... +...#... +: 8 +....... +....... +....... +....... +####### +...#... +...#... +...#... +: 9 +...#... +...#... +...#... +...#... +####### +....... +....... +....... +: 10 +...#... +...#... +...#... +...#... +####### +...#... +...#... +...#... diff --git a/src/genfont.c b/src/genfont.c new file mode 100644 index 00000000..d8e0a046 --- /dev/null +++ b/src/genfont.c @@ -0,0 +1,115 @@ +/* + * Apple // emulator for Linux: Font compiler + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#define _GNU_SOURCE + + +/* I'm not sure if this is the correct way to detect libc 5/4. I long + * since removed it from my system. + */ +#ifdef __GLIBC__ +#if __GLIBC__ == 1 + +/* Older Linux C libraries had getline removed (to humor programs that + * used that name for their own functions), but kept getdelim */ +#define getline(l,s,f) getdelim(l,s,'\n',f) + +#endif /* __GLIBC__ == 1 */ +#endif /* __GLIBC__ */ + +#include +#include +#include +#include + +int main(void) +{ + unsigned char byte; + + char *line = 0; + size_t line_size = 0; + + int i,mx; + + printf("/* Apple II text font data\n" + " * \n" + " * THIS FILE IS AUTOMATICALLY GENERATED --- DO NOT EDIT\n" + " */\n"); + + i = 0x100; + + while (getline(&line,&line_size,stdin) != -1) + { + if (line[0] == ';') continue; + + if (line[0] == '=') + { + char *name,*size; + + name = line + 1; + while (isspace(*name)) name++; + size = strchr(name,','); + *size++ = 0; + mx = i = strtol(size,0,0); + + printf("\nconst unsigned char %s[%d] =\n{\n ",name,i*8); + + continue; + } + + i--; + + if (line[0] == ':') + { + int j = 8; + + while (j--) + { + int k; + + getline(&line,&line_size,stdin); + k = 8; + byte = 0; + while (k--) + { + byte <<= 1; + byte += (line[k] == '#'); + } + + if (j) + printf("0x%02x, ",byte); + else if (i) + printf("0x%02x,\n ",byte); /* last byte in glyph */ + else + printf("0x%02x\n};\n",byte); /* last item in array */ + } + } + else break; + } + + + if (i) + { + fprintf(stderr, + "Trouble with font file at character 0x%02x\n", + mx-i-1); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); + +} + diff --git a/src/genglue b/src/genglue new file mode 100755 index 00000000..200e25ae --- /dev/null +++ b/src/genglue @@ -0,0 +1,5 @@ +#! /bin/sh +echo '/* Automatically Generated -- do not edit */' +echo '#include "gluepro.h"' +grep -E -h '^(GLUE_)|(#if)|(#endif)|(#else)|(#elif)' $* +exit 0 diff --git a/src/glue.h b/src/glue.h new file mode 100644 index 00000000..57a16e78 --- /dev/null +++ b/src/glue.h @@ -0,0 +1,28 @@ +/* + * Apple // emulator for Linux: Glue macros + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#define GLUE_FIXED_READ(func,address) +#define GLUE_FIXED_WRITE(func,address) +#define GLUE_BANK_READ(func,pointer) +#define GLUE_BANK_WRITE(func,pointer) +#define GLUE_BANK_MAYBEWRITE(func,pointer) + +#define GLUE_C_WRITE(func) \ + void unglued_##func(int ea, unsigned char d) /* you complete definition */ + +#define GLUE_C_READ(func) \ + unsigned char unglued_##func(int ea) /* you complete definition */ + diff --git a/src/gluepro.h b/src/gluepro.h new file mode 100644 index 00000000..7c4f71eb --- /dev/null +++ b/src/gluepro.h @@ -0,0 +1,75 @@ +/* + * Apple // emulator for Linux: Glue file prologue for Intel 386 + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#define __ASSEMBLY__ +#include + +#define GLUE_FIXED_READ(func,address) \ +E(func) movb SN(address)(%edi),%al; \ + ret; + +#define GLUE_FIXED_WRITE(func,address) \ +E(func) movb %al,SN(address)(%edi); \ + ret; + +#define GLUE_BANK_READ(func,pointer) \ +E(func) addl SN(pointer),%edi; \ + movb (%edi),%al; \ + subl SN(pointer),%edi; \ + ret; + +#define GLUE_BANK_WRITE(func,pointer) \ +E(func) addl SN(pointer),%edi; \ + movb %al,(%edi); \ + subl SN(pointer),%edi; \ + ret; + +#define GLUE_BANK_MAYBEWRITE(func,pointer) \ +E(func) addl SN(pointer),%edi; \ + cmpl $0,SN(pointer); \ + jz 1f; \ + movb %al,(%edi); \ +1: ret; + + +#define GLUE_C_WRITE(func) \ +E(func) pushl %eax; \ + andl $0xff,%eax; \ + pushl %ecx; \ + pushl %edx; \ + pushl %eax; \ + pushl %edi; \ + call SN(unglued_##func); \ + popl %edx; /* dummy */ \ + popl %edx; /* dummy */ \ + popl %edx; \ + popl %ecx; \ + popl %eax; \ + ret; \ + +#define GLUE_C_READ(func) \ +E(func) pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + pushl %edi; \ + call SN(unglued_##func); \ + movb %al,12(%esp); \ + popl %edx; /* dummy */ \ + popl %edx; \ + popl %ecx; \ + popl %eax; \ + ret; + diff --git a/src/interface.c b/src/interface.c new file mode 100644 index 00000000..0f0e5c91 --- /dev/null +++ b/src/interface.c @@ -0,0 +1,1229 @@ +/* + * Apple // emulator for Linux: Configuration Interface + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "keys.h" +#include "disk.h" +#include "misc.h" +#include "video.h" +#include "cpu.h" +#include "prefs.h" + +static struct stat statbuf; +static int altdrive; + +/*#define undoc_supported 1*/ +/*#else*/ +/*#define undoc_supported 0*/ + +#ifdef APPLE_IIE +#define iie_supported 1 +#else +#define iie_supported 0 +#endif + +static void pad_string(char *s, char c, int len) { + char *p; + + for (p = s; ((*p != '\0') && (p-s < len-1)); p++); + while (p-s < len-1) { + *p++ = c; + } + *p = '\0'; +} + +/* in keys.c */ +//extern void c_mouse_close(); + +/* from joystick.c */ +#ifdef PC_JOYSTICK +extern int c_open_joystick(); +extern void c_calculate_joystick_parms(); +extern void c_close_joystick(); +extern void c_calibrate_joystick(); +extern long js_timelimit; +#endif + + +/* ------------------------------------------------------------------------- + c_load_interface_font() + ------------------------------------------------------------------------- */ + +void c_load_interface_font() +{ + /* Only codes 0x20 -- 0x8A are actually used. But I feel safer + * explicitly initializing all of them. + */ + + video_loadfont_int(0x00,0x40,ucase_glyphs); + video_loadfont_int(0x40,0x20,ucase_glyphs); + video_loadfont_int(0x60,0x20,lcase_glyphs); + video_loadfont_int(0x80,0x40,ucase_glyphs); + video_loadfont_int(0xC0,0x20,ucase_glyphs); + video_loadfont_int(0xE0,0x20,lcase_glyphs); + + video_loadfont_int(0x80,11,interface_glyphs); +} + +/* ------------------------------------------------------------------------- + c_interface_print() + ------------------------------------------------------------------------- */ +void c_interface_print( int x, int y, int cs, unsigned char *s ) +{ + int i; + + for (i = x; *s; i++, s++) + video_plotchar( i, y, cs, *s ); + +} + +/* ------------------------------------------------------------------------- + c_interface_redo_bottom() + ------------------------------------------------------------------------- */ + +void c_interface_redo_bottom() { + + c_interface_print( 1, 21, 2, + " Use arrow keys (or Return) to modify " + ); + c_interface_print( 1, 22, 2, + " parameters. (Press ESC to exit menu) " + ); +} + +/* ------------------------------------------------------------------------- + c_interface_redo_diskette_bottom() + ------------------------------------------------------------------------- */ + +void c_interface_redo_diskette_bottom() { + c_interface_print( 1, 21, 2, + " Move: Arrows, PGUP, PGDN, HOME, END. " + ); + c_interface_print( 1, 22, 2, + " Return and 'w' select, ESC cancels. " + ); +} + +/* ------------------------------------------------------------------------- + c_interface_translate_screen() + ------------------------------------------------------------------------- */ + +#define IsGraphic(c) ((c) == '|' || ((c) >= 0x80 && (c) <= 0x8A)) +#define IsInside(x,y) ((x) >= 0 && (x) <= 39 && (y) >= 0 && (y) <= 23) + +void c_interface_translate_screen( unsigned char screen[24][41] ) +{ + static char map[11][3][4] ={ { "...", + ".||", + ".|." }, + + { "...", + "||.", + ".|." }, + + { ".|.", + ".||", + "..." }, + + { ".|.", + "||.", + "..." }, + + { ".|.", + ".|.", + ".|." }, + + { "...", + "|||", + "..." }, + + { ".|.", + ".||", + ".|." }, + + { ".|.", + "||.", + ".|." }, + + { "...", + "|||", + ".|." }, + + { ".|.", + "|||", + "..." }, + + { ".|.", + "|||", + ".|." } }; + + int x, y, i, j, k; + + for (y = 0; y < 24; y++) + for (x = 0; x < 40; x++) + { + if (screen[ y ][ x ] == '|') + { + int flag = 0; + + for (k = 10; !flag && k >= 0; flag ? : k--) + { + flag = 1; + + for (i = y - 1; flag && i <= y + 1; i++) + for (j = x - 1; flag && j <= x + 1; j++) + if (IsInside(j, i)) + if (!(IsGraphic( screen[ i ][ j ])) && + (map[k][ i - y + 1 ][ j - x + 1 ] == '|')) + flag = 0; + else; + else + if (map[k][ i - y + 1 ][ j - x + 1 ] == '|') + flag = 0; + } + + if (flag) + screen[ y ][ x ] = 0x80 + k; + } + } +} + +int c_interface_cut_name(char *name) +{ + char *p = name + strlen(name) - 1; + int is_gz = 0; + + if (p >= name && *p == 'z') + { + p--; + if (p >= name && *p == 'g') + { + p--; + if (p >= name && *p == '.') { + *p-- = '\0'; + is_gz = 1; + } + } + } + + return is_gz; +} + +void c_interface_cut_gz(char *name) +{ + char *p = name + strlen(name) - 1; + + p--; + p--; + *p = '\0'; +} + +#define GZ_EXT ".gz" +#define GZ_EXT_LEN 3 +#define DISK_EXT ".dsk" +#define DISK_EXT2 ".nib" +#define DISK_EXT_LEN 4 + +/* does name end with ".gz" ? */ +int c_interface_is_gz(const char *name) +{ + size_t len = strlen( name ); + + if (len > GZ_EXT_LEN) { /* shouldn't have a file called ".gz"... */ + /*name += len - GZ_EXT_LEN;*/ + return ((strcmp(name+len-GZ_EXT_LEN, GZ_EXT) == 0) ? 1 : 0); + } + + return 0; +} + + +/* does name end with ".nib{.gz}" */ +int c_interface_is_nibblized(const char *name) +{ + size_t len = strlen( name ); + + if (c_interface_is_gz(name)) + len -= GZ_EXT_LEN; + + if (!strncmp(name + len - DISK_EXT_LEN, DISK_EXT2, DISK_EXT_LEN)) + return 1; + + return 0; +} + + +int c_interface_disk_select(const struct dirent *e) +{ + static char cmp[ DISKSIZE ]; + size_t len; + const char *p; + + strncpy( cmp, disk_path, DISKSIZE ); + strncat( cmp, "/", DISKSIZE ); + strncat( cmp, e -> d_name, DISKSIZE ); + + /* don't show disk in alternate drive */ + if (!strcmp(cmp, disk6.disk[altdrive].file_name)) + return 0; + + /* show directories except '.' and '..' at toplevel. */ + stat(cmp, &statbuf); + if (S_ISDIR(statbuf.st_mode) && strcmp(".", e->d_name) && + !(!strcmp("..", e->d_name) && !strcmp(disk_path, "/"))) + return 1; + + p = e->d_name; + len = strlen(p); + + if (len > GZ_EXT_LEN && (!strcmp(p + len - GZ_EXT_LEN, GZ_EXT))) { + len -= GZ_EXT_LEN; + } + + /* true if .dsk or .nib extension */ + if (!strncmp(p + len - DISK_EXT_LEN, DISK_EXT, DISK_EXT_LEN)) + return 1; + if (!strncmp(p + len - DISK_EXT_LEN, DISK_EXT2, DISK_EXT_LEN)) + return 1; + + return 0; +} + +/* ------------------------------------------------------------------------- + c_interface_exit() + ------------------------------------------------------------------------- */ + +void c_interface_exit() +{ + video_setpage(!!(softswitches & SS_SCREEN)); + video_redraw(); +} + + +/* ------------------------------------------------------------------------- + c_interface_select_diskette() + ------------------------------------------------------------------------- */ + +void c_interface_select_diskette( int drive ) +{ + static unsigned char screen[24][41] = + { "||||||||||||||||||||||||||||||||||||||||", + "| Insert diskette into Drive _, Slot 6 |", + "||||||||||||||||||||||||||||||||||||||||", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "||||||||||||||||||||||||||||||||||||||||", + "| Move: Arrows, PGUP, PGDN, HOME, END. |", + "| Return and 'w' select, ESC cancels. |", + "||||||||||||||||||||||||||||||||||||||||" }; + + struct dirent **namelist; + int i, entries; + pid_t pid; + static int curpos=0; + int ch; + + screen[ 1 ][ 29 ] = (drive == 0) ? 'A' : 'B'; + + video_setpage( 0 ); + + c_interface_translate_screen( screen ); + + NEXTDIR: + for (i = 0; i < 24; i++) + c_interface_print( 0, i, 2, screen[ i ] ); + + altdrive = (drive == 0) ? 1 : 0; + if (!strcmp("", disk_path)) + sprintf(disk_path, "/"); + + /* set to users privilege level for directory access */ + entries = scandir(disk_path, &namelist, + c_interface_disk_select, alphasort); + + if (entries <= 0) { + /* 1/17/97 NOTE: scandir (libc5.3.12) seems to freak on broken + symlinks. so you won't be able to read from some + legitimate directories... */ + c_interface_print( 6, 11, 0, "Problem reading directory!" ); + sprintf(disk_path, "/"); + usleep(1500000); + c_interface_exit(); + return; + } + + if (curpos >= entries) + curpos = entries - 1; + + for (;;) { + for (i = 0; i < 17; i++) { + int ent_no = curpos - 8 + i, slen; + int in_drive = 0; + + strcpy( temp, " " ); + if (ent_no >= 0 && ent_no < entries) { + snprintf(temp, TEMPSIZE, "%s/%s", + disk_path, namelist[ent_no]->d_name); + if (!strcmp(temp, disk6.disk[drive].file_name)) + in_drive = 1; + + stat(temp, &statbuf); + if (S_ISDIR(statbuf.st_mode)) + snprintf(temp, TEMPSIZE, " %s/", + namelist[ ent_no ] -> d_name ); + else + snprintf(temp, TEMPSIZE, " %s", + namelist[ ent_no ] -> d_name ); + if (c_interface_cut_name(temp)) { + strncat(temp, " ", TEMPSIZE); + } + /* write protected disk in drive? */ + else if ((in_drive) && (disk6.disk[drive].protected)) + strncat(temp, (drive == 0) ? " " : " ", TEMPSIZE); + else if (in_drive) + strncat(temp, (drive == 0) ? " " : " ", TEMPSIZE); + } + + slen = strlen( temp ); + while (slen < 38) + temp[ slen++ ] = ' '; + temp[ 38 ] = '\0'; + + c_interface_print(1, i + 3, ent_no == curpos, temp); + } + + do + { + ch = c_mygetch(1); + } + while (ch == -1); + + if (ch == kUP) /* Arrow up */ + if (curpos > 0) + curpos--; + else; + else if (ch == kDOWN) /* Arrow down */ + if (curpos < entries - 1) + curpos++; + else; + else if (ch == kPGDN) /* Page down */ + { + curpos += 16; + if (curpos > entries - 1) + curpos = entries - 1; + } + else if (ch == kPGUP) /* Page up */ + { + curpos -= 16; + if (curpos < 0) + curpos = 0; + } + else if (ch == kHOME) /* Home */ + curpos = 0; + else if (ch == kEND) /* End */ + curpos = entries - 1; + else if (ch == kESC) /* ESC */ + { + for (i = 0; i < entries; i++) + free(namelist[ i ]); + free(namelist); + c_interface_exit(); + return; + } + else if ((ch == 13) || (toupper(ch) == 'W')) /* Return */ + { + int len, cmpr = 0; + + snprintf(temp, TEMPSIZE, "%s/%s", + disk_path, namelist[ curpos ] -> d_name ); + len = strlen(disk_path); + + /* handle disk currently in the drive */ + if (!strcmp(temp, disk6.disk[drive].file_name)) { + /* reopen disk, forcing write enabled */ + if (toupper(ch) == 'W') { + if (c_new_diskette_6( + drive, + temp, + disk6.disk[drive].compressed, + disk6.disk[drive].nibblized, 0)) + { + c_interface_print( 1, 21, 0, + " Disk is read and write protected. " ); + c_interface_print( 1, 22, 0, + " " ); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + + for (i = 0; i < entries; i++) + free(namelist[ i ]); /* clean up */ + free(namelist); + c_interface_exit(); /* resume emulation */ + return; + } + + /* eject the disk and start over */ + c_eject_6(drive); + for (i = 0; i < entries; i++) + free(namelist[ i ]); /* clean up */ + free(namelist); + goto NEXTDIR; /* I'm lazy */ + } + + /* read another directory */ + stat(temp, &statbuf); + if (S_ISDIR(statbuf.st_mode)) { + if (toupper(ch) == 'W') continue;/* can't protect this */ + + if ((disk_path[len-1]) == '/') disk_path[--len] = '\0'; + + if (!strcmp("..", namelist[curpos]->d_name)) { + while (--len && (disk_path[len] != '/')) + disk_path[len] = '\0'; + } + else if (strcmp(".", namelist[curpos]->d_name)) + snprintf(disk_path + len, DISKSIZE-len, "/%s", + namelist[curpos]->d_name); + for (i = 0; i < entries; i++) + free(namelist[ i ]); /* clean up */ + free(namelist); + goto NEXTDIR; /* I'm lazy */ + } + + /* uncompress the gziped disk */ + if (c_interface_is_gz(temp)) + { + if ((pid = fork())) { /* parent process */ + c_interface_print( 1, 21, 0, + " Uncompressing... " ); + c_interface_print( 1, 22, 0, + " " ); + if (waitpid(pid, NULL, 0) == -1) { + c_interface_print( 1, 21, 0, + " Problem gunzip'ing " ); + c_interface_print( 1, 22, 0, + " " ); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + } else if (!pid) { /* child process */ + /* privileged mode - gzip in place */ + if (execl("/bin/gzip", "/bin/gzip", + "-d", temp, NULL) == -1) + { + snprintf(temp, TEMPSIZE, "%s", sys_errlist[errno]); + perror("\tproblem"); + c_interface_print( 1, 21, 0, + " Problem exec'ing /bin/gzip -d " ); + c_interface_print( 1, 22, 0, temp); + usleep(1500000); + exit(-1); + } + } else { + snprintf(temp, TEMPSIZE, "%s", sys_errlist[errno]); + c_interface_print( 1, 21, 0, + " Cannot fork! " ); + c_interface_print( 1, 22, 0, temp); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + + c_interface_cut_gz( temp ); + cmpr = 1; + } + + /* gzip the last disk */ + if (disk6.disk[drive].compressed) { + /* gzip the last disk if it was compressed_6 */ + + if ((pid = fork())) { /* parent process */ + /* privileged mode - gzip in place */ + c_interface_print( 1, 21, 0, + " Compressing old diskette... " ); + c_interface_print( 1, 22, 0, + " " ); + if (waitpid(pid, NULL, 0) == -1) { + c_interface_print( 1, 21, 0, + " Problem gzip'ing " ); + c_interface_print( 1, 22, 0, + " " ); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + } else if (!pid) { /* child process */ + /* privileged mode - gzip in place */ + if (execl("/bin/gzip", "/bin/gzip", + disk6.disk[drive].file_name, NULL) == -1) + { + c_interface_print( 1, 21, 0, + " Problem exec'ing /bin/gzip " ); + c_interface_print( 1, 22, 0, temp); + usleep(1500000); + exit(-1); + } + } else { + snprintf(temp, TEMPSIZE, "%s", sys_errlist[errno]); + c_interface_print( 1, 21, 0, + " Cannot fork! " ); + c_interface_print( 1, 22, 0, temp); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + } + + /* now try to change the disk */ + if (c_new_diskette_6( + drive, temp, cmpr, c_interface_is_nibblized(temp), + (toupper(ch) != 'W'))) + { + c_interface_print( 1, 21, 0, + " Disk is read and write protected. " ); + c_interface_print( 1, 22, 0, + " " ); + usleep(1500000); + c_mygetch(1); + c_interface_redo_diskette_bottom(); + continue; + } + + for (i = 0; i < entries; i++) + free(namelist[ i ]); /* clean up */ + free(namelist); + c_interface_exit(); /* resume emulation */ + return; + } + } +} + +/* ------------------------------------------------------------------------- + c_interface_parameters() + ------------------------------------------------------------------------- */ + +#define NUM_OPTIONS 14 +#define SAVE_SETTINGS 12 +#define QUIT_EMULATOR 13 +#define PATH_OPTION 1 +#define CALIBRATE_OPTION 6 + +void c_interface_parameters() +{ + static unsigned char screen[24][41] = + { "||||||||||||||||||||||||||||||||||||||||", + "| Apple II Emulator for Linux |", + "| Originally by |", + "| Alexander Jean-Claude Bottema |", + "||||||||||||||||||||||||||||||||||||||||", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "| |", + "||||||||||||||||||||||||||||||||||||||||", + "| F1 F2: Slot6 Drive A, Drive B |", + "| F4 : Pause Emulation |", + "| F5 : Keyboard Layout |", + "| F9 : Toggle Max Speed |", + "| F10 : This Menu |", + "||||||||||||||||||||||||||||||||||||||||", + "| Use arrow keys (or Return) to modify |", + "| parameters. (Press ESC to exit menu) |", + "||||||||||||||||||||||||||||||||||||||||" }; + + static char *options[NUM_OPTIONS] = + { " Speed : ", /* 0 */ + " Path : ", + " Mode : ", + " Color : ", + " Sound : ", + " Joystick : ", /* 5 */ + " Calibrate ", + " JS Range : ", + " Origin X : ", + " Origin Y : ", + " JS Sens. : ", /* 10 */ + " JS Sample: ", + " Save ", + " Quit " }; + + int i; + int ch; + static int option = 0; + static int cur_y = 0, cur_off = 0, cur_x = 0, cur_pos = 0; + int current_mode = apple_mode; + + if (!iie_supported && (current_mode == 2)) + current_mode = apple_mode = 0; + + /* reset the x position, so we don't lose our cursor if path changes */ + cur_x = 0; + video_setpage( 0 ); + + c_interface_translate_screen( screen ); + + for (i = 0; i < 24; i++) + c_interface_print( 0, i, 2,screen[ i ] ); + + for (;;) { + for (i = 0; i < 9; i++) { + cur_off = option - 8; + if (cur_off < 0) cur_off = 0; + + c_interface_print( 1, 5 + i, cur_y == i, options[ i + cur_off ] ); + + switch (i + cur_off) + { + case 0: + snprintf(temp, TEMPSIZE, "%03d", + MAX_APPLE_DELAY + 1 - cpu65_delay); + break; + case 1: + strncpy(temp, disk_path + cur_pos, 24); + temp[24] = '\0'; + break; + case 2: +#ifdef APPLE_IIE + sprintf(temp, "%s", (apple_mode == 0) ? "][+ " : + (apple_mode == 1) ? "][+ undocumented" : + "//e "); +#else + sprintf(temp, "%s", (apple_mode == 0) ? "][+ " : + "][+ undocumented"); +#endif + break; + case 3: + sprintf(temp, "%s", (color_mode == 0) ? "Black/White " : + (color_mode == 1) ? "Lazy Color " : + (color_mode == 2) ? "Color " : + (color_mode == 3) ? "Lazy Interp." : + "Interpolated"); + break; + case 4: + sprintf(temp, "%s", (sound_mode == 0) ? "Off " : + "PC speaker"); + break; + case 5: + sprintf(temp, "%s", (joy_mode == JOY_KYBD) ? "Linear " : + (joy_mode == JOY_DIGITAL) ? "Digital " : + (joy_mode == JOY_PCJOY) ? "PC Joystick" : + "Off "); + break; + case 6: /* calibrate joystick */ + strcpy( temp, "" ); + break; + case 7: + sprintf(temp, "%02x", joy_range); + break; + case 8: + sprintf(temp, "%02x", joy_center_x); + break; + case 9: + sprintf(temp, "%02x", joy_center_y); + break; + case 10: + sprintf(temp, "%03d%%", joy_step ); + break; + case 11: +#ifdef PC_JOYSTICK + sprintf(temp, "%ld", js_timelimit); +#else + sprintf(temp, "%s", ""); +#endif + break; + case SAVE_SETTINGS: /* save settings */ + strcpy( temp, "" ); + break; + case QUIT_EMULATOR: /* quit emulator */ + strcpy( temp, "" ); + break; + default: + break; + } + + pad_string(temp, ' ', 26); + if (i+cur_off != 1) + c_interface_print(14, 5 + i, 0, temp); + else { + int j; + + for (j = 0; j < 24; j++) + if (cur_x != j) + { + if (temp[ j ] == '\0') + { + video_plotchar( 14 + j, 5+i, 0, ' ' ); + j++; + break; + } + else + video_plotchar( 14 + j, 5+i, 0, temp[ j ] ); + } + else + { + if (temp[ j ] == '\0') + { + video_plotchar( 14 + j, 5+i, option==1,' ' ); + j++; + break; + } + else + video_plotchar( 14 + j, 5+i, option==1, + temp[ j ]); + + } + for (; j < 24; j++) + video_plotchar( 14 + j, 5+i, 0, ' ' ); + } + } + + do + { + ch = c_mygetch(1); + } + while (ch == -1); + + if (ch == kUP) { /* Arrow up */ + if (option > 8) { + option--; /* only dec option */ + } else if (option > 0) { + option--; /* dec option */ + cur_y--; /* and dec y position */ + } else { + option = NUM_OPTIONS-1; /* wrap to last option */ + cur_y = 8; /* wrap to last y position */ + } + } + else if (ch == kDOWN) { /* Arrow down */ + if (cur_y < 8) { + option++; /* inc option */ + cur_y++; /* and inc y position */ + } else if (option < NUM_OPTIONS-1) { + option++; /* only inc option */ + } else { + cur_y = option = 0; /* wrap both to first */ + } + } + else if (ch == kLEFT) { /* Arrow left */ + switch (option) { + case 0: /* inc speed */ + if (cpu65_delay < MAX_APPLE_DELAY) + cpu65_delay++; + break; + case 1: /* path */ + if (cur_x > 0) + cur_x--; + else + if (cur_pos > 0) + cur_pos--; + break; + case 2: /* apple mode */ + apple_mode--; + if (apple_mode < 0) + apple_mode = 2; + if ((apple_mode == 2) && !iie_supported) + apple_mode = 1; + break; + case 3: /* color mode */ + if (color_mode == 0) + color_mode = 4; + else + --color_mode; + break; + case 4: /* sound mode */ + if (sound_mode == 0) + sound_mode = 1; + else + --sound_mode; + break; + case 5: /* joystick mode */ +#ifdef PC_JOYSTICK + if (joy_mode == 0) + joy_mode = 3; +#else + if (joy_mode == 0) + joy_mode = 2; +#endif + else + --joy_mode; + break; + case 6: /* calibrate */ + break; + case 7: /* range */ + if (joy_range > 10) { + --joy_range; + joy_center_x = joy_range/2; + joy_center_y = joy_range/2; + } + break; + case 8: /* origin x */ + if (joy_center_x > 0) + joy_center_x--; + break; + case 9: /* origin y */ + if (joy_center_y > 0) + joy_center_y--; + break; + case 10: /* sensitivity */ + if (joy_step > 1) + joy_step--; + break; + case 11: +#ifdef PC_JOYSTICK + if (js_timelimit > 2) /* joystick sample rate */ + --js_timelimit; +#endif + break; + case SAVE_SETTINGS: /* save settings */ + case QUIT_EMULATOR: /* quit emulator */ + break; + } + } + else if (ch == kRIGHT) { /* Arrow right */ + switch (option) { + case 0: /* dec speed */ + if (cpu65_delay > 1) + cpu65_delay--; + break; + case 1: /* path */ + if (cur_x < 23) + { + if (disk_path[cur_pos + cur_x] != '\0') + cur_x++; + } + else + if (disk_path[cur_pos + cur_x] != '\0') + cur_pos++; + break; + case 2: /* apple mode */ + apple_mode++; + if (apple_mode > 2) + apple_mode = 0; + if ((apple_mode == 2) && !iie_supported) + apple_mode = 0; + break; + case 3: /* color mode */ + color_mode++; + if (color_mode > 4) + color_mode = 0; + break; + case 4: /* sound mode */ + sound_mode++; + if (sound_mode > 1) + sound_mode = 0; + break; + case 5: /* joystick mode */ +#ifdef PC_JOYSTICK + if (joy_mode == 3) + joy_mode = 0; +#else + if (joy_mode == 2) + joy_mode = 0; +#endif + else + ++joy_mode; + break; + case 6: /* calibrate */ + break; + case 7: /* range */ + if (joy_range < 256) { + ++joy_range; + joy_center_x = joy_range/2; + joy_center_y = joy_range/2; + } + break; + case 8: /* origin x */ + if (joy_center_x < joy_range-1) + joy_center_x++; + break; + case 9: /* origin y */ + if (joy_center_y < joy_range-1) + joy_center_y++; + break; + case 10: /* sensitivity */ + if (joy_step < 100) + joy_step++; + break; + case 11: /* joystick sample rate */ +#ifdef PC_JOYSTICK + js_timelimit++; +#endif + break; + case SAVE_SETTINGS: /* save settings */ + case QUIT_EMULATOR: /* quit emulator */ + break; + } + } + else if (ch == kESC) { /* exit menu */ + c_initialize_sound(); + video_set(0); /* redo colors */ +#ifdef PC_JOYSTICK + if (joy_mode == JOY_PCJOY) { + c_close_joystick(); /* close the joystick */ + c_open_joystick(); /* reopen the joystick */ + half_joy_range = joy_range/2; + c_calculate_joystick_parms(); + } else { + c_close_joystick(); + } +#endif + /* reboot machine if different */ + if (current_mode != apple_mode) + cpu65_interrupt(RebootSig); + + c_interface_exit(); + return; + } + else { + /* got a normal character setting path */ + if (ch >= ' ' && ch < 127 && option == PATH_OPTION) { + int i; + + strncpy(temp, disk_path, TEMPSIZE); + for (i = strlen(temp); i >= cur_pos + cur_x; i--) + temp[ i + 1 ] = temp[ i ]; + temp[ cur_pos + cur_x ] = ch; + strncpy(disk_path, temp, DISKSIZE); + if (cur_x < 23) + cur_x++; + else + if (disk_path[cur_pos + cur_x] != '\0') + cur_pos++; + } + + /* Backspace or delete setting path */ + if ((ch == 127 || ch == 8) && (cur_pos + cur_x - 1 >= 0) && + (option == 1)) + { + int i; + + for (i = cur_pos + cur_x - 1; disk_path[ i ] != '\0'; i++) + disk_path[ i ] = disk_path[ i + 1 ]; + + if (cur_x > 0) + cur_x--; + else + if (cur_pos > 0) + cur_pos--; + } +#ifdef PC_JOYSTICK + /* calibrate joystick */ + if ((ch == 13) && (option == CALIBRATE_OPTION)) { + c_calibrate_joystick(); + } +#endif + /* save settings */ + if ((ch == 13) && (option == SAVE_SETTINGS)) { + save_settings(); + } + + /* quit apple II simulator */ + if (ch == 13 && option == QUIT_EMULATOR) { + int ch; + + c_interface_print( + 1, 22, 0, " Are you sure? (Y/N) " ); + while ((ch = c_mygetch(1)) == -1) ; + ch = toupper(ch); + if (ch == 'Y') + { + c_eject_6( 0 ); + c_eject_6( 1 ); +#ifdef PC_JOYSTICK + c_close_joystick(); +#endif + printf("Linux! ...and there were much rejoicing! " + "oyeeeeh...\n"); + video_shutdown(); + exit( 0 ); + } + + c_interface_print( 0, 22, 2, screen[ 22 ] ); + + } + } + } +} + +#if 0 +/* ------------------------------------------------------------------------- + c_interface_words() - this is not valid anymore. + if anyone has his email, let the maintainer know! + ------------------------------------------------------------------------- */ + +void c_interface_words() +{ + static unsigned char screen[24][41] = + { "||||||||||||||||||||||||||||||||||||||||", + "| Apple II+ Emulator Version 0.01 |", + "||||||||||||||||||||||||||||||||||||||||", + "| If you have problems with your |", + "| keyboard concerning the mapping of |", + "| various keys, please let me know. |", + "| I use a Swedish keyboard for myself |", + "| and the scancodes may differ from US |", + "| keyboards (or other countries as |", + "| well). Currently, my email address |", + "| is: d91a1bo@meryl.csd.uu.se. This |", + "| address is valid at least one more |", + "| year, i.e. as long as I am Computer |", + "| Science student at the University |", + "| of Uppsala. \"...and there were much |", + "| rejoicing! oyeeeeeh\" |", + "| |", + "| |", + "| |", + "| |", + "| / Alexander Oct 9 1994 |", + "||||||||||||||||||||||||||||||||||||||||", + "| (Press any key to exit) |", + "||||||||||||||||||||||||||||||||||||||||" }; + + int i; + + video_setpage( 0 ); + + c_interface_translate_screen( screen ); + + for (i = 0; i < 24; i++) + c_interface_print( 0, i, 2, screen[ i ] ); + + while (c_mygetch(1) == -1) { } + c_interface_exit(); +} +#endif /* if 0 */ + +/* ------------------------------------------------------------------------- + c_interface_keyboard_layout() + ------------------------------------------------------------------------- */ + +void c_interface_keyboard_layout() +{ + static unsigned char screen1[24][41] = + { "||||||||||||||||||||||||||||||||||||||||", + "| Apple II+ US Keyboard Layout |", + "||||||||||||||||||||||||||||||||||||||||", + "| |", + "| 1! 2\" 3# 4$ 5% 6& 7' 8( 9) 0 :* -= |", + "| Q W E R T Y U I O P@ CR |", + "| A S D F G H J K L ;+ <- ->|", + "| Z X C V B N^ M ,< .> /? |", + "| Where <- -> are the left and right |", + "| arrow keys respectively. |", + "| |", + "| Joystick emulation on numeric keypad |", + "| 7 8 9 for various directions. |", + "| 4 6 Press 5 to center linear |", + "| 1 2 3 joystick. |", + "| |", + "| Ctrl-PrintScrn/SysRq is REBOOT. |", + "| Ctrl-Pause/Break is RESET. |", + "| Pause/Break alone pauses emulation. |", + "| Alt Left and Alt Right are Apple |", + "| Keys (Joystick buttons 0 & 1). |", + "||||||||||||||||||||||||||||||||||||||||", + "| (Press any key to exit) |", + "||||||||||||||||||||||||||||||||||||||||" }; + +#ifdef APPLE_IIE + static unsigned char screen2[24][41] = + { "||||||||||||||||||||||||||||||||||||||||", + "| Apple //e US Keyboard Layout |", + "||||||||||||||||||||||||||||||||||||||||", + "| |", + "|1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ dl|", + "| Q W E R T Y U I O P [{ ]} \\| |", + "|cp A S D F G H J K L ;: '\" CR |", + "|sh Z X C V B N M ,< .> /? sh |", + "|ctrl |", + "| |", + "| Where dl is DEL, cp is CAPS, CR is |", + "| RETURN, sh is SHIFT, ctrl is CONTROL.|", + "| Arrow keys are as is. |", + "| Joystick emulation is same as the |", + "| ][+. |", + "| |", + "| Ctrl-PrintScrn/SysRq is REBOOT. |", + "| Ctrl-Pause/Break is RESET. |", + "| Pause/Break alone pauses emulation. |", + "| Alt Left and Alt Right are Apple |", + "| Keys (Joystick buttons 0 & 1). |", + "||||||||||||||||||||||||||||||||||||||||", + "| (Press any key to exit) |", + "||||||||||||||||||||||||||||||||||||||||" }; +#endif + + int i; + + video_setpage( 0 ); + +#ifdef APPLE_IIE + if (apple_mode == 2) { + c_interface_translate_screen(screen2); + for (i = 0; i < 24; i++) + c_interface_print( 0, i, 2, screen2[ i ] ); + } else +#endif + { + c_interface_translate_screen(screen1); + for (i = 0; i < 24; i++) + c_interface_print( 0, i, 2, screen1[ i ] ); + } + + while (c_mygetch(1) == -1) { } + c_interface_exit(); +} diff --git a/src/interface.h b/src/interface.h new file mode 100644 index 00000000..3423b5e4 --- /dev/null +++ b/src/interface.h @@ -0,0 +1,28 @@ +/* + * Apple // emulator for Linux: Exported menu routines + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef A2_INTERFACE_H +#define A2_INTERFACE_H + +void c_interface_print( int x, int y, int cs, unsigned char *s ); +void c_interface_redo_bottom();/* bit of a HACK? */ +void c_load_interface_font(); +void c_interface_keyboard_layout(); +void c_interface_parameters(); +void c_interface_exit(); +void c_interface_translate_screen(unsigned char screen[24][41]); +void c_interface_select_diskette(int); +#endif diff --git a/src/joystick.c b/src/joystick.c new file mode 100644 index 00000000..56fa66df --- /dev/null +++ b/src/joystick.c @@ -0,0 +1,207 @@ +/* + * Apple // emulator for Linux: Joystick calibration routines + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "video.h" +#include "keys.h" +#include "misc.h" +#include "prefs.h" + +int js_fd = -1; /* joystick file descriptor */ +struct JS_DATA_TYPE js; /* joystick data struct */ + +int js_lowerrange_x, + js_upperrange_x, + js_lowerrange_y, + js_upperrange_y, + js_offset_x, + js_offset_y; + +float + js_adjustlow_x, + js_adjustlow_y, + js_adjusthigh_x, + js_adjusthigh_y; + + +/* ------------------------------------------------------------------------- + c_open_joystick() - opens joystick device and sets timelimit value + ------------------------------------------------------------------------- */ +int c_open_joystick() { + if (js_fd < 0) { + if ((js_fd = open("/dev/js0", O_RDONLY)) < 0) { + + /* try again with another name */ + if ((js_fd = open("/dev/joystick", O_RDONLY)) < 0) + return 1;/* problem */ + } + /* set timelimit value */ + if (ioctl(js_fd, JS_SET_TIMELIMIT, &js_timelimit) == -1) + return 1;/* problem */ + } + return 0;/* no problem */ +} + +/* ------------------------------------------------------------------------- + c_close_joystick() - closes joystick device + ------------------------------------------------------------------------- */ +void c_close_joystick() { + if (js_fd < 0) + return; + close(js_fd); + js_fd = -1; +} + + +/* ------------------------------------------------------------------------- + * c_calculate_joystick_parms() - calculates parameters for joystick + * device. assumes that device extremes have already been determined. + * ------------------------------------------------------------------------- */ +void c_calculate_joystick_parms() { + + js_lowerrange_x = js_center_x - js_min_x; + js_upperrange_x = js_max_x - js_center_x; + js_lowerrange_y = js_center_y - js_min_y; + js_upperrange_y = js_max_y - js_center_y; + + js_offset_x = js_min_x; + js_offset_y = js_min_y; + + js_adjustlow_x = (float)half_joy_range / (float)js_lowerrange_x; + js_adjustlow_y = (float)half_joy_range / (float)js_lowerrange_y; + js_adjusthigh_x = (float)half_joy_range / (float)js_upperrange_x; + js_adjusthigh_y = (float)half_joy_range / (float)js_upperrange_y; +} + +/* ------------------------------------------------------------------------- + c_calibrate_joystick() - calibrates joystick. determines extreme + and center coordinates. assumes that it can write to the interface + screen. + ------------------------------------------------------------------------- */ +void c_calibrate_joystick () { + int almost_done, done; + unsigned char x_val, y_val; + + /* reset all the extremes */ + js_max_x = -1; + js_max_y = -1; + js_min_x = MAXINT; + js_min_y = MAXINT; + + /* open joystick device if not open */ + if (js_fd < 0) { + if (c_open_joystick()) { /* problem opening device */ + c_interface_print( + 1, 21, 0, " " ); + c_interface_print( + 1, 22, 0, " cannot open joystick device. " ); + video_sync(0); + usleep(1500000); + c_interface_redo_bottom(); + return;/* problem */ + } + } + + c_interface_print( + 1, 21, 0, " Move joystick to all extremes then " ); + c_interface_print( + 1, 22, 0, " center it and press a button. " ); + video_sync(0); + usleep(1500000); + c_interface_print( + 1, 21, 0, " " ); + c_interface_print( + 1, 22, 0, " " ); + + almost_done = done = 0; /* not done calibrating */ + while ((read(js_fd, &js, JS_RETURN) > 0) && (!done)) + { + sprintf (temp, " x = %04x, y = %04x", js.x, js.y); + c_interface_print(1, 22, 0, temp); + video_sync(0); + if (js_max_x < js.x) + js_max_x = js.x; + if (js_max_y < js.y) + js_max_y = js.y; + + if (js_min_x > js.x) + js_min_x = js.x; + if (js_min_y > js.y) + js_min_y = js.y; + + if (js.buttons != 0x00) /* press */ + almost_done = 1; + if (almost_done && (js.buttons == 0x00)) /* release */ + done = 1; + } + + js_center_x = js.x; + js_center_y = js.y; + + printf("js_min_x = %d\n", js_min_x); + printf("js_min_y = %d\n", js_min_y); + printf("js_max_x = %d\n", js_max_x); + printf("js_max_y = %d\n", js_max_y); + printf("js_center_x = %d\n", js_center_x); + printf("js_center_y = %d\n", js_center_y); + printf("\n"); + + c_calculate_joystick_parms(); /* determine the parms */ + + printf("js_lowerrange_x = %d\n", js_lowerrange_x); + printf("js_lowerrange_y = %d\n", js_lowerrange_y); + printf("js_upperrange_x = %d\n", js_upperrange_x); + printf("js_upperrange_y = %d\n", js_upperrange_y); + printf("\n"); + printf("js_offset_x = %d\n", js_offset_x); + printf("js_offset_y = %d\n", js_offset_y); + printf("\n"); + printf("js_adjustlow_x = %f\n", js_adjustlow_x); + printf("js_adjustlow_y = %f\n", js_adjustlow_y); + printf("js_adjusthigh_x = %f\n", js_adjusthigh_x); + printf("js_adjusthigh_y = %f\n", js_adjusthigh_y); + printf("\n"); + + c_interface_print( + 1, 21, 0, " Press a button to continue. " ); + video_sync(0); + + /* show the normalized values until user presses button */ + while ((read(js_fd, &js, JS_RETURN) > 0) && js.buttons == 0x00) { + x_val = (js.x < js_center_x) + ? (js.x - js_offset_x) * js_adjustlow_x + : (js.x - (js_center_x/*+js_offset_x*/)) * js_adjusthigh_x + + half_joy_range; + + y_val = (js.y < js_center_y) + ? (js.y - js_offset_y) * js_adjustlow_y + : (js.y - (js_center_y/*+js_offset_y*/)) * js_adjusthigh_y + + half_joy_range; + sprintf(temp, " x = %02x, y = %02x", x_val, y_val); + c_interface_print(1, 22, 0, temp); + video_sync(0); + } + c_interface_redo_bottom(); + video_sync(0); +} diff --git a/src/keys.c b/src/keys.c new file mode 100644 index 00000000..1a928041 --- /dev/null +++ b/src/keys.c @@ -0,0 +1,461 @@ +/* + * Apple // emulator for Linux: Keyboard handler + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include + +#include "keys.h" +#include "misc.h" +#include "video.h" +#include "interface.h" +#include "cpu.h" +#include "prefs.h" + +/* from misc.c */ +extern uid_t user, privileged; + +#ifdef DEBUGGER +/* from debugger.c */ +extern void c_do_debugging(); +#endif + + +/* parameters for generic and keyboard-simulated joysticks */ +short joy_x = 127; +short joy_y = 127; +unsigned char joy_button0 = 0; +unsigned char joy_button1 = 0; +unsigned char joy_button2 = 0; + +#ifdef PC_JOYSTICK +#include +int x_val, y_val; +#endif + +static int next_key = -1; +static char caps_lock = 1; /* is enabled */ +static int in_mygetch = 0; + +/* ---------------------------------------------------- + Keymap. Mapping scancodes to Apple II+ US Keyboard + ---------------------------------------------------- */ +static int apple_ii_keymap_plain[128] = + { -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */ + '7', '8', '9', '0', ':', '-', 8 , 27 , /* 08-15 */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */ + 'O', 'P', -1 , 8 , 13 , -1 , 'A', 'S', /* 24-31 */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 32-39 */ + 8 , -1 , -1 , 21 , 'Z', 'X', 'C', 'V', /* 40-47 */ + 'B', 'N', 'M', ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , -1, JB1 , RST , kHOME , -1 , /* 96-103 */ + kPGUP , 8 , 21 , kEND , -1 , kPGDN, JB2 , -1, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* (pause) */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_ii_keymap_ctrl[128] = + { -1 , 027, '1', '2', '3', '4', '5', '6', /* 00-07 */ + '7', '8', '9', '0', ':', '-', 8 , 27 , /* 08-15 */ + 17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */ + 15 , 16 , -1 , 8 , 13 , -1 , 1 , 19 , /* 24-31 */ + 4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */ + 8 , -1 , -1 , 21 , 26 , 24 , 3 , 22 , /* 40-47 */ + 2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , BOT, JB1 , RST , kHOME , -1 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, -1 , kPGDN, JB2 , -1, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_ii_keymap_shifted[128] = + { -1 , 27 , '!', '"', '#', '$', '%', '&', /* 00-07 */ + 39 , '(', ')', '0', '*', '=', 8 , 27 , /* 08-15 */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */ + 'O', '@', -1 , 8 , 13 , -1 , 'A', 'S', /* 24-31 */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', /* 32-39 */ + 8 , -1 , -1 , 21 , 'Z', 'X', 'C', 'V', /* 40-47 */ + 'B', '^', 'M', '<', '>', '?', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , -1 , JB1 , RST , kHOME , -1 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, -1 , kPGDN, JB2 , -1, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +#ifdef APPLE_IIE +/* ---------------------------------------------------- + //e Keymap. Mapping scancodes to Apple //e US Keyboard + ---------------------------------------------------- */ +static int apple_iie_keymap_plain[128] = + { -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */ + '7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 16-23 */ + 'o', 'p', '[', ']', 13 , -1 , 'a', 's', /* 24-31 */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 32-39 */ + '\'', '`', -1 ,'\\', 'z', 'x', 'c', 'v', /* 40-47 */ + 'b', 'n', 'm', ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , -1, JB1 , RST , kHOME , 11 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_iie_keymap_ctrl[128] = + { -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */ + '7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */ + 17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */ + 15 , 16 , 27 , 29 , 13 , -1 , 1 , 19 , /* 24-31 */ + 4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */ + '\'', '`', -1 ,'\\', 26 , 24 , 3 , 22 , /* 40-47 */ + 2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , BOT, JB1 , RST , kHOME , 11 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_iie_keymap_shifted[128] = + { -1 , 27 , '!', '@', '#', '$', '%', '^', /* 00-07 */ + '&', '*', '(', ')', '_', '+', 8 , 9 , /* 08-15 */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */ + 'O', 'P', '{', '}', 13 , -1 , 'A', 'S', /* 24-31 */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 32-39 */ + '"', '~', -1 , '|', 'Z', 'X', 'C', 'V', /* 40-47 */ + 'B', 'N', 'M', '<', '>', '?', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , -1 , JB1 , RST , kHOME , 11 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_iie_keymap_caps[128] = + { -1 , 27 , '1', '2', '3', '4', '5', '6', /* 00-07 */ + '7', '8', '9', '0', '-', '=', 8 , 9 , /* 08-15 */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16-23 */ + 'O', 'P', '[', ']', 13 , -1 , 'A', 'S', /* 24-31 */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', /* 32-39 */ + '\'', '`', -1 ,'\\', 'Z', 'X', 'C', 'V', /* 40-47 */ + 'B', 'N', 'M', ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , -1, JB1 , RST , kHOME , 11 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ + +static int apple_iie_keymap_shift_ctrl[128] = + { -1 , 27 , '1', 0 , '3', '4', '5', 30 , /* 00-07 */ + '7', '8', '9', '0', 31 , '=', 8 , 9 , /* 08-15 */ + 17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 , /* 16-23 */ + 15 , 16 , 27 , 29 , 13 , -1 , 1 , 19 , /* 24-31 */ + 4 , 6 , 7 , 8 , 10 , 11 , 12 , ';', /* 32-39 */ + '\'', '`', 28 , -1 , 26 , 24 , 3 , 22 , /* 40-47 */ + 2 , 14 , 13 , ',', '.', '/', -1 , -1 , /* 48-55 */ + JB0 , ' ', -1 , kF1 , kF2 , kF3 , kF4 , kF5 , /* 56-63 */ + kF6 , kF7 , kF8 , kF9 , kF10, -1 , -1 , JUL, /* 64-71 */ + J_U, JUR, S_D, J_L, J_C, J_R, S_I, JDL, /* 72-79 */ + J_D, JDR, -1 , -1 , -1 , kF11, kF12, -1 , /* 80-87 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* 88-95 */ + -1 , -1 , -1 , BOT, JB1 , RST , kHOME , 11 , /* 96-103 */ + kPGUP , 8 , 21 , kEND, 10 , kPGDN, JB2, 127, /* 104-111 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , kF4 /* pause */, /* 112-119 */ + -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }; /* 120-127 */ +#endif + +static unsigned short max_speed = 0; +static char key_pressed[ 256 ]; + + +/* ---------------------------------------------------- + functions + ---------------------------------------------------- */ + +/* ------------------------------------------------------------------------- + * This routine is called periodically to update the state of the emulator. + * -handles switching to menus + * -polls PC Joystick + * -update palette for flashing text + * ------------------------------------------------------------------------- */ +void c_periodic_update(int dummysig) { + int current_key; + + video_sync(0); + + if (next_key >= 0) + { + current_key = next_key; + next_key = -1; + + if (current_key < 128) { + apple_ii_64k[0][0xC000] = current_key | 0x80; + apple_ii_64k[1][0xC000] = current_key | 0x80; + } else switch (current_key) { + case RST: + cpu65_interrupt(ResetSig); + break; + case BOT: + cpu65_interrupt(RebootSig); + break; + case J_C: + joy_x = joy_center_x; + joy_y = joy_center_y; + break; + case kF1: + c_interface_select_diskette( 0 ); + break; + case kF2: + c_interface_select_diskette( 1 ); + break; + case kF4: + while (c_mygetch(1) == -1) { }/*busy loop*/ + break; + case kF5: + c_interface_keyboard_layout(); + break; +#ifdef DEBUGGER + case kF7: + cpu65_interrupt(EnterDebugSig); + break; +#endif +#if 0 + case kF8: + c_interface_words(); + break; +#endif + case kF9: + if (max_speed != 0) + cpu65_delay = max_speed, max_speed = 0; + else + max_speed = cpu65_delay, cpu65_delay = 1; + break; + case kF10: + if (max_speed != 0) + cpu65_delay = max_speed, max_speed = 0; + c_interface_parameters(); + break; + } + } + + /* simulated joystick */ + if (joy_mode == JOY_KYBD) { + if (key_pressed[ SCODE_J_U ]) + { + if (joy_y > joy_step) + joy_y -= joy_step; + else + joy_y = 0; + } + + if (key_pressed[ SCODE_J_D ]) + { + if (joy_y < joy_range - joy_step) + joy_y += joy_step; + else + joy_y = joy_range-1; + } + + if (key_pressed[ SCODE_J_L ]) + { + if (joy_x > joy_step) + joy_x -= joy_step; + else + joy_x = 0; + } + + if (key_pressed[ SCODE_J_R ]) + { + if (joy_x < joy_range - joy_step) + joy_x += joy_step; + else + joy_x = joy_range-1; + } + } +#ifdef PC_JOYSTICK + else if ((joy_mode == JOY_PCJOY) && !(js_fd < 0)) { + read(js_fd, &js, JS_RETURN); + + x_val = (js.x < js_center_x) + ? (js.x - js_offset_x) * js_adjustlow_x + : (js.x - js_center_x) * js_adjusthigh_x + half_joy_range; + + y_val = (js.y < js_center_y) + ? (js.y - js_offset_y) * js_adjustlow_y + : (js.y - js_center_y) * js_adjusthigh_y + half_joy_range; + + joy_y = (y_val > 0xff) ? 0xff : (y_val < 0) ? 0 : y_val; + joy_x = (x_val > 0xff) ? 0xff : (x_val < 0) ? 0 : x_val; + +/* almost_x = (x_val > 0xff) ? 0xff : (x_val < 0) ? 0 : x_val; */ +/* adj_x = (3-(joy_y/0x40)) + 10; */ +/* turnpt_x = joy_y + adj_x; */ +/* almost_x = (almost_x < turnpt_x) */ +/* ? almost_x */ +/* : (almost_x - turnpt_x) * adjusthigh_x; */ + +/* joy_x = (almost_x > 0xff) ? 0xff : (almost_x < 0) ? 0 : almost_x; */ + + /* sample buttons only if apple keys aren't pressed. keys get set to + * 0xff, and js buttons are set to 0x80. */ + if (!(joy_button0 & 0x7f)) + joy_button0 = (js.buttons & 0x01) ? 0x80 : 0x0; + if (!(joy_button1 & 0x7f)) + joy_button1 = (js.buttons & 0x02) ? 0x80 : 0x0; + if (!(joy_button2 & 0x7f)) + joy_button2 = (js.buttons & 0x03) ? 0x80 : 0x0; + } +#endif + else if (joy_mode == JOY_OFF) + joy_x = joy_y = 256; +} + +#ifdef DEBUGGER +/* Called from cpu code. Perhaps should be moved to misc.c, but was + * abstracted from function above... + */ +void enter_debugger(void) +{ + setitimer(ITIMER_VIRTUAL,&timer_off,0); + c_do_debugging(); + setitimer(ITIMER_VIRTUAL,&timer_on,0); +} +#endif /* DEBUGGER */ + +/* ------------------------------------------------------------------------- + void c_read_raw_key() : handle a scancode + ------------------------------------------------------------------------- */ +void c_read_raw_key(int scancode, int pressed) { + int *keymap = NULL; + + /* determine which key mapping to use */ +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE || in_mygetch) { + /* set/reset caps lock */ + if (key_pressed[ SCODE_CAPS ]) + caps_lock = !caps_lock; + + if ((key_pressed[ SCODE_L_SHIFT ] || /* shift-ctrl */ + key_pressed[ SCODE_R_SHIFT ]) && + (key_pressed[ SCODE_L_CTRL ] || + key_pressed[ SCODE_R_CTRL ])) + keymap = apple_iie_keymap_shift_ctrl; + else if (key_pressed[ SCODE_L_CTRL ] || /* ctrl */ + key_pressed[ SCODE_R_CTRL ]) + keymap = apple_iie_keymap_ctrl; + else if (key_pressed[ SCODE_L_SHIFT ] || /* shift */ + key_pressed[ SCODE_R_SHIFT ]) + keymap = apple_iie_keymap_shifted; + else if (caps_lock) /* caps lock */ + keymap = apple_iie_keymap_caps; + else /* plain */ + keymap = apple_iie_keymap_plain; + } else +#endif + { + if (key_pressed[ SCODE_L_CTRL ] || + key_pressed[ SCODE_R_CTRL ]) + keymap = apple_ii_keymap_ctrl; + else if (key_pressed[ SCODE_L_SHIFT ] || + key_pressed[ SCODE_R_SHIFT ]) + keymap = apple_ii_keymap_shifted; + else + keymap = apple_ii_keymap_plain; + } + + /* key is pressed */ + if (pressed) { + + key_pressed[ scancode ] = 1; + + switch (keymap[ scancode ]) { + case JB0: + joy_button0 = 0xff;/* open apple */ + break; + case JB1: + joy_button1 = 0xff;/* closed apple */ + break; + case JB2: + joy_button2 = 0xff;/* unused? */ + break; + default: + next_key = keymap[scancode]; + break; + } + } + + /* key is released */ + else { + key_pressed[ scancode ] = 0; + switch (keymap[ scancode ]) { + case JB0: + joy_button0 = 0x00; + break; + case JB1: + joy_button1 = 0x00; + break; + case JB2: + joy_button2 = 0x00; + break; + } + } +} + +int c_mygetch(int block) +{ + int retval; + + in_mygetch = 1; + + if (block) while (next_key == -1) + video_sync(1); + else + video_sync(0); + + in_mygetch = 0; + + retval = next_key; + next_key = -1; + + return retval; +} diff --git a/src/keys.h b/src/keys.h new file mode 100644 index 00000000..aea89c41 --- /dev/null +++ b/src/keys.h @@ -0,0 +1,95 @@ +/* + * Apple // emulator for Linux: Keyboard definitions + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef A2_KEYS_H +#define A2_KEYS_H + +#define SCODE_L_CTRL 29 +#define SCODE_R_CTRL 97 +#define SCODE_L_SHIFT 42 +#define SCODE_R_SHIFT 54 +#define SCODE_CAPS 58 +#define SCODE_J_U 72 +#define SCODE_J_D 80 +#define SCODE_J_L 75 +#define SCODE_J_R 77 +#define SCODE_J_C 76 + +#define kF1 128 +#define kF2 129 +#define kF3 130 +#define kF4 131 +#define kF5 132 +#define kF6 133 +#define kF7 134 +#define kF8 135 +#define kF9 136 +#define kF10 137 +#define kF11 138 +#define kF12 139 +#define kPRNT 140 +#define RST kPRNT + +#define J_U 141 +#define J_D 142 +#define J_L 143 +#define J_R 144 +#define JUL 145 +#define JUR 146 +#define JDL 147 +#define JDR 148 + +#define JB0 149 +#define JB1 150 +#define JB2 151 + +#define S_D 152 +#define S_I 153 +#define J_C 154 +#define kPAUSE 155 +#define BOT kPAUSE + +#define kLEFT 8 /* 157 */ +#define kRIGHT 21 /* 158 */ +#define kUP 11 /* 159 */ +#define kDOWN 10 /* 160 */ + +#define kESC 27 /* 161 */ +#define kPGUP 162 +#define kHOME 163 +#define kPGDN 164 +#define kEND 165 + +#define TIMER_DELAY 30000L + + +#ifdef PC_JOYSTICK +extern int js_fd; +extern struct JS_DATA_TYPE js; +extern int js_offset_x, js_offset_y; +extern float js_adjustlow_x, js_adjustlow_y, js_adjusthigh_x, js_adjusthigh_y; +extern int c_open_joystick(void); +extern void c_calculate_joystick_parms(void); +extern void c_close_joystick(void); +extern void c_calibrate_joystick(void); +#endif + +void c_read_raw_key(int scancode, int pressed); +void c_periodic_update(int dummysig); +void enter_debugger(void); +int c_mygetch(int block); + +#endif diff --git a/src/memory.S b/src/memory.S new file mode 100644 index 00000000..a444ad29 --- /dev/null +++ b/src/memory.S @@ -0,0 +1,977 @@ +/* + * Apple // emulator for Linux: + * Functions for memory-access indirection table. + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include "apple2.h" +#include "cpu.h" +#include "misc.h" + + /* -------------------------------------------------------------------- + .................................................................... + Apple ][+ Memory documentation (//e differs mostly in softswitches) + + I use two jump tables; one for get_memory and one for set_memory + respectively. The jump tables contain exactly 64k entries to + avoid unnecessary range checking. Furthermore, special access + or to serve memory mapped I/O services are easily obtained by + patching the jump table with various routines. + + Apple 64k address space: + + (Two byte addresses are represented with least significant + byte first, e.g. address FA59 is represented as 59 FA) + + Address Description + + 0000 - 00FF Zero page RAM + 0100 - 01FF Stack + 0200 - 03EF RAM + 03F0 - 03F1 Address for BRK instruction + (normally 59 FA = FA59) + 03F2 - 03F3 Soft entry vector (normally BF 9D = 9DBF) + 03F4 Power-up byte + 03F5 - 03F7 Jump instruction to the subroutine which + handles Applesoft II &-commands + (normally 4C 58 FF = JMP FF58) + 03F8 - 03FA Jump instruction to the subroutine which + handles User CTRL-Y commands + (normally 4C 65 FF = JMP FF65) + 03FB - 03FD Jump instruction to the subroutine which + handles Non-Maskable Interrupts (NMI) + (normally 4C 65 FF = JMP FF65) + 03FE - 03FF Address of the subroutine which handles + Interrupt ReQuests (IRQ) + (normally 65 FF = FF65) + 0400 - 07FF Basically primary video text page + 0478 - 047F I/O Scratchpad RAM Addresses for Slot 0 - 7 + 04F8 - 04FF - " " - + 0578 - 057F - " " - + 05F8 - 05FF - " " - + 0678 - 067F - " " - + 06F8 - 06FF - " " - + 0778 - 077F - " " - + 07F8 - 07FF - " " - + ----- These two addresses are pretty strange; the values + provided were inconsistent at least on my Apple II + 05F8 Holds the slot number of the disk + controller card from which DOS was + booted. + 07F8 Holds the slot number (CX, X = Slot #) + of the slot that is currently active. + + 0800 - 0BFF Basically secondary video text page + + 0C00 - 1FFF Plain RAM + 2000 - 3FFF Primary video hires page (RAM) + 4000 - 5FFF Secondary video Hi-Res page (RAM) + 6000 - BFFF Plain RAM + (Normally the operating system is + loaded into ~= 9C00 - BFFF) + C000 - C00F Keyboard data + (C00X contains the character ASCII + code of the pressed key. The + value is available at any C00X + address) + C010 - C01F Clear Keyboard strobe + C020 - C02F Cassette output toggle + C030 - C03F Speaker toggle + C040 - C04F Utility strobe + C050 Set graphics mode + C051 Set text mode + C052 Set all text or graphics + C053 Mix text and graphics + C054 Display primary page + C055 Display secondary page + C056 Display low-res graphics + C057 Display hi-res graphics + C058 - C05F Annunciator outputs + C060 Cassette input + C061 - C063 Pushbutton inputs (button 1, 2 and 3) + C064 - C067 Game controller inputs + C068 - C06F Same as C060 - C067 + C070 - C07F Game controller strobe + C080 - C08F Slot 0 I/O space (usually a language card) + --- If language card + C080 Reset language card + Read mode enabled + Write mode disabled + Read from language card + Write to ROM (impossible of course) + C081 --- First access + Read mode disabled + Read from ROM + --- On second access + Write mode enabled + Write to language card + C082 --- (Disable language card) + Read mode disabled + Write mode disabled + Read from ROM + Write to ROM + C083 --- First access + Read mode enabled + Read from language card + --- On second access + Write mode enabled + Write to language card + C088 - C08B Same as C080 - C083, but + switch to second bank, i.e. + map addresses D000-DFFF to + other 4k area. + C100 - C1FF Slot 1 PROM + C200 - C2FF Slot 2 PROM + C300 - C3FF Slot 3 PROM + C400 - C4FF Slot 4 PROM + C500 - C5FF Slot 5 PROM + C600 - C6FF Slot 6 PROM + C700 - C7FF Slot 7 PROM + C800 - CFFF Expansion ROM (for peripheral cards) + CFFF Disable access to expansion ROM for + ALL peripheral cards. + D000 - DFFF ROM or 4k RAM if language card is + enabled. However, there are TWO 4k + banks that can be mapped onto addresses + D000 - DFFF. See C088 - C08B. + E000 - FFFF ROM or 8k RAM if language card is + enabled. + ----------------------------------------------------------------- */ + + + .comm SN(softswitches),4 + + .comm SN(base_ramrd),4 + .comm SN(base_ramwrt),4 + .comm SN(base_textrd),4 + .comm SN(base_textwrt),4 + .comm SN(base_hgrrd),4 + .comm SN(base_hgrwrt),4 + + .comm SN(base_stackzp),4 + .comm SN(base_d000_rd),4 + .comm SN(base_d000_wrt),4 + .comm SN(base_e000_rd),4 + .comm SN(base_e000_wrt),4 + + .comm SN(base_cxrom),4 + .comm SN(base_c3rom),4 + +/* ram_nop, read_ram_default, write_ram_default: default ram/rom + read/write functions. */ +E(ram_nop) + ret + +E(read_unmapped_softswitch) + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + ret + +E(write_unmapped_softswitch) + ret + +E(read_keyboard) + movb SN(apple_ii_64k)+0xC000, %al + ret + +E(read_keyboard_strobe) + andb $0x7f, SN(apple_ii_64k)+0xC000 + andb $0x7f, SN(apple_ii_64k)+0x1C000 + movb SN(apple_ii_64k)+0xC000, %al /* HACK: necessary? */ + ret + +E(read_random) + pushal + call SN(c_read_random) + popal + movb SN(random_value), %al + ret + +E(read_speaker_toggle_pc) + inb $0x61, %al + xorb $0x2, %al + outb %al, $0x61 + ret + +E(read_switch_primary_page) + testl $SS_PAGE2, SN(softswitches) + jnz _read_switch_primary + ret +_read_switch_primary: + andl $~(SS_PAGE2|SS_SCREEN), SN(softswitches) + pushal + pushl $0 + call SN(video_setpage) + addl $4, %esp + popal + ret + +E(read_switch_secondary_page) + testl $SS_PAGE2, SN(softswitches) + jz _read_switch_secondary + ret +_read_switch_secondary: + orl $(SS_PAGE2|SS_SCREEN), SN(softswitches) + pushal + pushl $1 + call SN(video_setpage) + addl $4, %esp + popal + ret + +#ifdef APPLE_IIE +/* PAGE2 off. if 80STORE on then we use main text page1, and if HIRES + on we also use main hires page1, regardless of RAMRD and + RAMWRT. */ +E(iie_page2_off) + testl $SS_PAGE2, SN(softswitches) # already off? + jz ram_nop + andl $~(SS_PAGE2|SS_SCREEN), SN(softswitches) + testl $SS_80STORE, SN(softswitches) + jz _iie_page2_off_hires_off # no 80STORE + andl $~(SS_TEXTRD|SS_TEXTWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_textrd) + movl $SN(apple_ii_64k), SN(base_textwrt) + testl $SS_HIRES, SN(softswitches) + jz _iie_page2_off_hires_off # no HIRES + andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrrd) + movl $SN(apple_ii_64k), SN(base_hgrwrt) +_iie_page2_off_hires_off: + pushal + pushl $0 # page 1 main + call SN(video_setpage) + addl $4, %esp + popal +/* call SN(video_redraw)# redraw */ + ret + + +/* PAGE2 on. if 80STORE on then we use aux text page 1, and if HIRES + on we also use aux hires page 1, regardless of RAMRD and + RAMWRT. */ +E(iie_page2_on) + testl $SS_PAGE2, SN(softswitches) # already on? + jnz ram_nop + orl $SS_PAGE2, SN(softswitches) + testl $SS_80STORE, SN(softswitches) + jz _iie_page2_on_80store_off # no 80STORE + orl $(SS_TEXTRD|SS_TEXTWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_textrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt) + testl $(SS_HIRES), SN(softswitches) + jz _iie_page2_on_cont + orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) +_iie_page2_on_cont: + ret + +_iie_page2_on_80store_off: # no 80STORE + orl $SS_SCREEN, SN(softswitches) + pushal + pushl $1 # page 2 main + call SN(video_setpage) + addl $4, %esp + popal +/* call SN(video_redraw)# redraw */ + ret +#endif + +E(read_switch_graphics) + testl $SS_TEXT, SN(softswitches) + jz ram_nop + andl $~SS_TEXT, SN(softswitches) + call SN(video_redraw) + ret + +E(read_switch_text) + testl $SS_TEXT, SN(softswitches) + jnz ram_nop + orl $SS_TEXT, SN(softswitches) + call SN(video_redraw) + ret + +E(read_switch_no_mixed) + testl $SS_MIXED, SN(softswitches) + jz ram_nop + andl $~SS_MIXED, SN(softswitches) + call SN(video_redraw) + ret + +E(read_switch_mixed) + testl $SS_MIXED, SN(softswitches) + jnz ram_nop + orl $SS_MIXED, SN(softswitches) + call SN(video_redraw) + ret + +E(read_switch_lores) + testl $SS_HIRES, SN(softswitches) + jz ram_nop + andl $~SS_HIRES, SN(softswitches) + call SN(video_redraw) + ret + +E(read_switch_hires) + testl $SS_HIRES, SN(softswitches) + jnz ram_nop + orl $SS_HIRES, SN(softswitches) + call SN(video_redraw) + ret + +#ifdef APPLE_IIE +/* HIRES off. use RAMRD/RAMWRT offsets for hires page 1. */ +E(iie_hires_off) + testl $SS_HIRES, SN(softswitches) # already off? + jz ram_nop + andl $~(SS_HIRES|SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrrd) + movl $SN(apple_ii_64k), SN(base_hgrwrt) + testl $SS_RAMRD,SN(softswitches) + jz iie_hires_off_no_ramrd + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) + orl $SS_HGRRD, SN(softswitches) +iie_hires_off_no_ramrd: + testl $SS_RAMWRT,SN(softswitches) + jz iie_hires_off_no_ramwrt + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) + orl $SS_HGRWRT, SN(softswitches) +iie_hires_off_no_ramwrt: + call SN(video_redraw) # update screen + ret + +/* HIRES on. if 80STORE on, use PAGE2 offset for hires page 1. */ +E(iie_hires_on) + testl $SS_HIRES, SN(softswitches) # already on? + jnz ram_nop + orl $SS_HIRES, SN(softswitches) # hires on + testl $SS_80STORE, SN(softswitches) + jz iie_hires_on_80store_off # no 80STORE + testl $SS_PAGE2, SN(softswitches) + jz iie_hires_on_80store_aux + andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrrd) + movl $SN(apple_ii_64k), SN(base_hgrwrt) + jmp iie_hires_on_80store_off +iie_hires_on_80store_aux: + orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) +iie_hires_on_80store_off: + call SN(video_redraw) # update screen + ret +#endif + +/*****************************************************************************/ + +.comm joy_trigger0, 2 +.comm joy_trigger1, 2 +.comm joy_trigger2, 2 +.comm joy_trigger3, 2 + +E(read_button0) + movb SN(joy_button0), %al + ret + +E(read_button1) + movb SN(joy_button1), %al + ret + +E(read_button2) + movb SN(joy_button2), %al + ret + +E(read_gc0) + cmpw $0xFF, joy_trigger0 + je read_gc0_cont + incw joy_trigger0 +read_gc0_cont: + movw joy_trigger0, %ax + cmpw %ax, SN(joy_x) + jge read_gc0_ff /* XXXX is this correct? */ + movb $0, %al + ret +read_gc0_ff: + movb $0xFF, %al + ret + +E(read_gc1) + cmpw $0xFF, joy_trigger1 + je read_gc1_cont + incw joy_trigger1 +read_gc1_cont: + movw joy_trigger1, %ax + cmpw %ax, SN(joy_y) + jge read_gc1_ff + movb $0, %al + ret +read_gc1_ff: + movb $0xFF, %al + ret + +/* HACK not doing anything... */ +E(iie_read_gc2) + ret + +E(iie_read_gc3) + ret + +E(read_gc_strobe) + movb $0, joy_trigger0 + movb $0, joy_trigger1 + movb $0, joy_trigger2 + movb $0, joy_trigger3 + ret + +E(iie_c080) + testl $SS_ALTZP, SN(softswitches) + jz lc_c080 + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c080: read RAM; no write; use $D000 bank 2. */ +E(lc_c080) + orl $SS_LCRAM|SS_BANK2, SN(softswitches) + andl $~(SS_LCSEC|SS_LCWRT), SN(softswitches) + movl $SN(language_banks)-0xD000, SN(base_d000_rd) + movl $SN(language_card)-0xE000, SN(base_e000_rd) + movl $0, SN(base_d000_wrt) + movl $0, SN(base_e000_wrt) + ret + +E(iie_c081) + testl $SS_ALTZP, SN(softswitches) + jz lc_c081 + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c081: read ROM; write RAM; use $D000 bank 2. */ +E(lc_c081) + testl $SS_LCSEC, SN(softswitches) + je lc_c081_exit + orl $SS_LCWRT, SN(softswitches) + movl $SN(language_banks)-0xD000, SN(base_d000_wrt) + movl $SN(language_card)-0xE000, SN(base_e000_wrt) +lc_c081_exit: + andl $~SS_LCRAM, SN(softswitches) + orl $SS_LCSEC|SS_BANK2, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_d000_rd) + movl $SN(apple_ii_64k), SN(base_e000_rd) + ret + +/* There is no iie_c082 --- since the LC is offline, no auxillary memory + * could be exposed. (ditto for c08a) */ + +/* c082: read ROM; no write; use $D000 bank 2. */ +E(lc_c082) + andl $~(SS_LCRAM|SS_LCWRT|SS_LCSEC), SN(softswitches) + orl $SS_BANK2, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_d000_rd) + movl $SN(apple_ii_64k), SN(base_e000_rd) + movl $0, SN(base_d000_wrt) + movl $0, SN(base_e000_wrt) + ret + +E(iie_c083) + testl $SS_ALTZP, SN(softswitches) + jz lc_c083 + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c083: read and write RAM; no write; use $D000 bank 2. */ +E(lc_c083) testl $SS_LCSEC, SN(softswitches) + je lc_c083_exit + orl $SS_LCWRT, SN(softswitches) + movl $SN(language_banks)-0xD000, SN(base_d000_wrt) + movl $SN(language_card)-0xE000, SN(base_e000_wrt) +lc_c083_exit: + orl $(SS_LCSEC|SS_LCRAM|SS_BANK2), SN(softswitches) + movl $SN(language_banks)-0xD000, SN(base_d000_rd) + movl $SN(language_card)-0xE000, SN(base_e000_rd) + ret + +E(iie_c088) + testl $SS_ALTZP, SN(softswitches) + jz lc_c088 + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c088: read RAM; no write; use $D000 bank 1. */ +E(lc_c088) + orl $(SS_LCRAM), SN(softswitches) + andl $~(SS_LCWRT|SS_LCSEC|SS_BANK2), SN(softswitches) + movl $SN(language_banks)-0xC000, SN(base_d000_rd) + movl $SN(language_card)-0xE000, SN(base_e000_rd) + movl $0, SN(base_d000_wrt) + movl $0, SN(base_e000_wrt) + ret + +E(iie_c089) + testl $SS_ALTZP, SN(softswitches) + jz lc_c089 + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c089: read ROM; write RAM; use $D000 bank 1. */ +E(lc_c089) + testl $SS_LCSEC, SN(softswitches) + jz lc_c089_exit + orl $SS_LCWRT, SN(softswitches) + movl $SN(language_banks)-0xC000, SN(base_d000_wrt) + movl $SN(language_card)-0xE000, SN(base_e000_wrt) +lc_c089_exit: + andl $~(SS_LCRAM|SS_BANK2), SN(softswitches) + orl $(SS_LCSEC), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_d000_rd) + movl $SN(apple_ii_64k), SN(base_e000_rd) + ret + +/* there is no iie_c08a */ + +/* c08a: read ROM; no write; use $D000 bank 1. */ +E(lc_c08a) + andl $~(SS_LCRAM|SS_LCWRT|SS_LCSEC|SS_BANK2), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_d000_rd) + movl $SN(apple_ii_64k), SN(base_e000_rd) + movl $0, SN(base_d000_wrt) + movl $0, SN(base_e000_wrt) + ret + +E(iie_c08b) + testl $SS_ALTZP, SN(softswitches) + jz lc_c08b + pushl $lc_to_auxmem /* sneak this code in when + * ][+ routine exits */ + +/* c08b: read and write RAM; use $D000 bank 1. */ +E(lc_c08b) + testl $SS_LCSEC, SN(softswitches) + jz lc_c08b_exit + orl $SS_LCWRT, SN(softswitches) + movl $SN(language_banks)-0xC000, SN(base_d000_wrt) + movl $SN(language_card)-0xE000, SN(base_e000_wrt) +lc_c08b_exit: + orl $(SS_LCRAM|SS_LCSEC), SN(softswitches) + andl $~SS_BANK2,SN(softswitches) + movl $SN(language_banks)-0xC000, SN(base_d000_rd) + movl $SN(language_card)-0xE000, SN(base_e000_rd) + ret +/* ------------------------------------------------------------------------- + * misc //e functions + * ------------------------------------------------------------------------- */ + +#ifdef APPLE_IIE + +/* 80STORE off. use RAMRD/RAMWRT for text/hires display page 1 */ +E(iie_80store_off) + testl $SS_80STORE, SN(softswitches) # already off? + jz ram_nop + andl $~(SS_80STORE|SS_TEXTRD|SS_TEXTWRT|SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k),SN(base_textrd) + movl $SN(apple_ii_64k),SN(base_textwrt) + movl $SN(apple_ii_64k),SN(base_hgrrd) + movl $SN(apple_ii_64k),SN(base_hgrwrt) + testl $SS_RAMRD, SN(softswitches) + jz iie_80store_off_noramrd + orl $(SS_TEXTRD|SS_HGRRD),SN(softswitches) + movl $SN(apple_ii_64k)+BANK2,SN(base_textrd) + movl $SN(apple_ii_64k)+BANK2,SN(base_hgrrd) +iie_80store_off_noramrd: + testl $SS_RAMRD, SN(softswitches) + jz iie_80store_off_noramwrt + orl $(SS_TEXTWRT|SS_HGRWRT),SN(softswitches) + movl $SN(apple_ii_64k)+BANK2,SN(base_textwrt) + movl $SN(apple_ii_64k)+BANK2,SN(base_hgrwrt) +iie_80store_off_noramwrt: + testl $SS_PAGE2, SN(softswitches) + jz ram_nop + orl $SS_SCREEN, SN(softswitches) + pushal + pushl $1 + call SN(video_setpage) + addl $4, %esp + popal +/* call SN(video_redraw) # redraw */ + ret + +/* 80STORE on. we use PAGE2 offset to access text page 1. if HIRES on + we also use PAGE2 offset to access hires page 1 */ +E(iie_80store_on) + testl $SS_80STORE, SN(softswitches) # already on? + jnz ram_nop + orl $SS_80STORE, SN(softswitches) + testl $SS_PAGE2, SN(softswitches) + jnz iie_80store_on_page2_on + andl $~(SS_TEXTRD|SS_TEXTWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_textrd) + movl $SN(apple_ii_64k), SN(base_textwrt) + testl $SS_HIRES, SN(softswitches) + jz iie_80store_on_cont + andl $~(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrrd) + movl $SN(apple_ii_64k), SN(base_hgrwrt) + jmp iie_80store_on_cont + +iie_80store_on_page2_on: + orl $(SS_TEXTRD|SS_TEXTWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_textrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt) + testl $SS_HIRES, SN(softswitches) + jz iie_80store_on_cont + orl $(SS_HGRRD|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) +iie_80store_on_cont: + andl $~SS_SCREEN, SN(softswitches) + pushal + pushl $0 # page 1 + call SN(video_setpage) + addl $4, %esp + popal +/* call SN(video_redraw) # redraw */ + ret + +return80: movb $0x80,%al + ret + +E(iie_check_80store) + testl $SS_80STORE,SN(softswitches) + jnz return80 + xorb %al,%al + ret + +/* RAMRD main. if 80STORE off then text/hires display pages are in + main memory. */ +E(iie_ramrd_main) + testl $SS_RAMRD, SN(softswitches) # already off? + jz ram_nop + andl $~SS_RAMRD, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_ramrd) + testl $SS_80STORE, SN(softswitches) # 80store? + jnz iie_ramrd_main_80store_on + andl $~(SS_TEXTRD|SS_HGRRD), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_textrd) + movl $SN(apple_ii_64k), SN(base_hgrrd) +/* call SN(video_redraw) # redraw */ + ret +iie_ramrd_main_80store_on: + testl $SS_HIRES, SN(softswitches) + jnz ram_nop + andl $~SS_HGRRD, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrrd) +/* call SN(video_redraw) # redraw */ + ret + +/* RAMRD aux. if 80STORE off then text/hires display pages are in aux + memory. */ +E(iie_ramrd_aux) + testl $SS_RAMRD, SN(softswitches) # already on? + jnz ram_nop + orl $SS_RAMRD, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_ramrd) + testl $SS_80STORE, SN(softswitches) # 80store? + jnz iie_ramrd_aux_80store_on + orl $(SS_TEXTRD|SS_HGRRD), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_textrd) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) +/* call SN(video_redraw) # redraw */ + ret +iie_ramrd_aux_80store_on: + testl $SS_HIRES, SN(softswitches) + jnz ram_nop # already set + orl $(SS_HGRRD), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrrd) +/* call SN(video_redraw) # redraw */ + ret + +E(iie_check_ramrd) + testl $SS_RAMRD, SN(softswitches) + jnz return80 + xorb %al,%al + ret + +/* RAMWRT main. if 80STORE off then text/hires display pages are in + main memory. */ +E(iie_ramwrt_main) + testl $SS_RAMWRT, SN(softswitches) # already off? + jz ram_nop + andl $~SS_RAMWRT, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_ramwrt) # main RAM + testl $SS_80STORE, SN(softswitches) # 80store? + jnz iie_ramwrt_main_80store_on + andl $~(SS_TEXTWRT|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k), SN(base_textwrt) + movl $SN(apple_ii_64k), SN(base_hgrwrt) +/* call SN(video_redraw) # redraw */ + ret +iie_ramwrt_main_80store_on: + testl $SS_HIRES, SN(softswitches) + jnz ram_nop + andl $~SS_HGRWRT, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_hgrwrt) +/* call SN(video_redraw) # redraw */ + ret + +/* RAMWRT aux. if 80STORE off then write to text/hires display pages + are in aux memory. */ +E(iie_ramwrt_aux) + testl $SS_RAMWRT, SN(softswitches) # already on? + jnz ram_nop + orl $SS_RAMWRT, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_ramwrt) # aux RAM + testl $SS_80STORE, SN(softswitches) # 80store? + jnz iie_ramwrt_aux_80store_on + orl $(SS_TEXTWRT|SS_HGRWRT), SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_textwrt) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) +/* call SN(video_redraw) # redraw */ + ret +iie_ramwrt_aux_80store_on: + testl $SS_HIRES, SN(softswitches) + jnz ram_nop + orl $SS_HGRWRT, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_hgrwrt) +/* call SN(video_redraw) # redraw */ + ret + +E(iie_check_ramwrt) + testl $SS_RAMWRT, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_altzp_main) + testl $SS_ALTZP, SN(softswitches) + jz 1f /* test if ALTZP already off - + * due to d000-bank issues it is + * *needed*, not just a shortcut */ + andl $~SS_ALTZP, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_stackzp) + andl $0xFFFF, SP_Reg + testl $SS_LCRAM|SS_LCWRT, SN(softswitches) + jz 1f /* shortest path for common case */ + testl $SS_LCRAM, SN(softswitches) + jz 2f + subl $0x2000, SN(base_d000_rd) + movl $SN(language_card)-0xE000, SN(base_e000_rd) +2: testl $SS_LCWRT, SN(softswitches) + jz 1f + subl $0x2000, SN(base_d000_wrt) + movl $SN(language_card)-0xE000, SN(base_e000_wrt) +1: ret + +E(iie_altzp_aux) + testl $SS_ALTZP, SN(softswitches) + jnz 1f /* test if ALTZP already on - + * due to d000-bank issues it is + * *needed*, not just a shortcut */ + orl $SS_ALTZP, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_stackzp) + orl $BANK2, SP_Reg + testl $SS_LCRAM|SS_LCWRT, SN(softswitches) + jz 1f /* shortest path for common case */ +lc_to_auxmem: /* called by lc routines */ + testl $SS_LCRAM, SN(softswitches) + jz 2f + addl $0x2000, SN(base_d000_rd) + movl $SN(language_card)-0xC000, SN(base_e000_rd) +2: testl $SS_LCWRT, SN(softswitches) + jz 1f + addl $0x2000, SN(base_d000_wrt) + movl $SN(language_card)-0xC000, SN(base_e000_wrt) +1: ret + +E(iie_check_altzp) + testl $SS_ALTZP, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_80col_off) + testl $SS_80COL, SN(softswitches) + jz ram_nop + andl $~SS_80COL, SN(softswitches) + testl $(SS_TEXT|SS_MIXED|SS_DHIRES), SN(softswitches) + jnz SN(video_redraw) + ret + +E(iie_80col_on) + testl $SS_80COL, SN(softswitches) + jnz ram_nop + orl $SS_80COL, SN(softswitches) + testl $(SS_TEXT|SS_MIXED|SS_DHIRES), SN(softswitches) + jnz SN(video_redraw) + ret + +E(iie_check_80col) + testl $SS_80COL, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_altchar_off) + testl $SS_ALTCHAR, SN(softswitches) + jz ram_nop + andl $~SS_ALTCHAR, SN(softswitches) + pushal + call SN(c_set_primary_char) + popal + ret + +E(iie_altchar_on) + testl $SS_ALTCHAR, SN(softswitches) + jnz ram_nop + orl $SS_ALTCHAR, SN(softswitches) + pushal + call SN(c_set_altchar) + popal + ret + +E(iie_check_altchar) + testl $SS_ALTCHAR, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +/* unset ioudis flag and read_gc_strobe */ +E(iie_ioudis_off) + andl $~SS_IOUDIS, SN(softswitches) + jmp SN(read_gc_strobe) + +/* set ioudis flag and read_gc_strobe */ +E(iie_ioudis_on) + orl $SS_IOUDIS, SN(softswitches) + jmp SN(read_gc_strobe) + +/* check ioudis flag and read_gc_strobe */ +E(iie_check_ioudis) + call SN(read_gc_strobe) + testl $SS_IOUDIS, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_dhires_on) + testl $SS_IOUDIS, SN(softswitches) + jz ram_nop + orl $SS_DHIRES, SN(softswitches) + call SN(video_redraw) + ret + +E(iie_dhires_off) + testl $SS_IOUDIS, SN(softswitches) + jz ram_nop + andl $~SS_DHIRES, SN(softswitches) + call SN(video_redraw) + ret + +/* check dhires flag and read_gc_strobe */ +E(iie_check_dhires) + call SN(read_gc_strobe) + testl $SS_DHIRES, SN(softswitches) + jnz return80 + ret + +E(iie_check_text) + testl $SS_TEXT, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_check_mixed) + testl $SS_MIXED, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_check_page2) + testl $SS_PAGE2, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_check_hires) + testl $SS_HIRES, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_check_bank) + testl $SS_BANK2, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +E(iie_check_lcram) + testl $SS_LCRAM, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +/* HACK not doing anything... */ +E(iie_check_vbl) + ret + + /* ---------------------------------- */ + +E(iie_c3rom_peripheral) + andl $~SS_C3ROM, SN(softswitches) + testl $SS_CXROM, SN(softswitches) + jnz 1f /* CXROM-internal preempts C3ROM */ + movl $SN(apple_ii_64k), SN(base_c3rom) +1: ret + +E(iie_c3rom_internal) + orl $SS_C3ROM, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_c3rom) + ret + +E(iie_check_c3rom) + testl $SS_C3ROM, SN(softswitches) + jz return80 + xorb %al, %al + ret + +E(iie_cxrom_peripheral) + andl $~SS_CXROM, SN(softswitches) + movl $SN(apple_ii_64k), SN(base_cxrom) + testl $SS_C3ROM, SN(softswitches) + jnz 1f + movl $SN(apple_ii_64k), SN(base_c3rom) +1: ret + +E(iie_cxrom_internal) + orl $SS_CXROM, SN(softswitches) + movl $SN(apple_ii_64k)+BANK2, SN(base_cxrom) + movl $SN(apple_ii_64k)+BANK2, SN(base_c3rom) + ret + +E(iie_check_cxrom) + testl $SS_CXROM, SN(softswitches) + jnz return80 + xorb %al, %al + ret + +/* HACK!!!!! - how does the expansion slot get referenced? need to handle other roms requesting to use this area!!!! */ +E(iie_read_slot_expansion) + orl SN(c8rom_offset), EffectiveAddr_E + movb SN(apple_ii_64k)(,EffectiveAddr_E,1), %al + andl $0xFFFF, EffectiveAddr_E + ret + +/* HACK!!!!! - how does the expansion slot get referenced? */ +E(iie_disable_slot_expansion) + ret + +#endif /* APPLE_IIE */ diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 00000000..22827e59 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,745 @@ +/* + * Apple // emulator for Linux: Miscellaneous support + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" +#include "video.h" +#include "disk.h" +#include "interface.h" +#include "keys.h" +#ifdef DEBUGGER +#include "debug.h" +#endif +#include "cpu.h" +#include "glue.h" +#include "prefs.h" + +const struct itimerval timer_off = {{0,0},{0,0}}; +const struct itimerval timer_on = {{0,TIMER_DELAY},{0,TIMER_DELAY}}; + +/* ---------------------------------- + internal apple2 variables + ---------------------------------- */ + +static unsigned char apple_ii_rom[12288]; +#ifdef APPLE_IIE +static unsigned char apple_iie_rom[32768]; /* //e */ +#endif + +#ifdef DEBUGGER +/* in debugger.c */ +extern int breakpoints[]; +extern int watchpoints[]; +extern int op_breakpoints[256]; +#endif + +GLUE_FIXED_READ(read_ram_default,apple_ii_64k) +GLUE_FIXED_WRITE(write_ram_default,apple_ii_64k) +GLUE_BANK_READ(read_ram_bank,base_d000_rd) +GLUE_BANK_MAYBEWRITE(write_ram_bank,base_d000_wrt) +GLUE_BANK_READ(read_ram_lc,base_e000_rd) +GLUE_BANK_MAYBEWRITE(write_ram_lc,base_e000_wrt) + +#ifdef APPLE_IIE + +GLUE_BANK_READ(iie_read_ram_default,base_ramrd) +GLUE_BANK_WRITE(iie_write_ram_default,base_ramwrt) +GLUE_BANK_READ(iie_read_ram_text_page0,base_textrd) +GLUE_BANK_WRITE(iie_write_screen_hole_text_page0,base_textwrt) +GLUE_BANK_READ(iie_read_ram_hires_page0,base_hgrrd) +GLUE_BANK_WRITE(iie_write_screen_hole_hires_page0,base_hgrwrt) + +GLUE_BANK_READ(iie_read_ram_zpage_and_stack,base_stackzp) +GLUE_BANK_WRITE(iie_write_ram_zpage_and_stack,base_stackzp) + +GLUE_BANK_READ(iie_read_slot3,base_c3rom) +GLUE_BANK_READ(iie_read_slotx,base_cxrom) + + + +/* ------------------------------------------------------------------------- + c_set_altchar() - set alternate character set + ------------------------------------------------------------------------- */ +void c_set_altchar() +{ + video_loadfont(0x40,0x20,mousetext_glyphs,1); + video_loadfont(0x60,0x20,lcase_glyphs,2); + + video_redraw(); +} + +/* ------------------------------------------------------------------------- + c_set_primary_char() - set primary character set + ------------------------------------------------------------------------- */ +void c_set_primary_char() +{ + video_loadfont(0x40,0x40,ucase_glyphs,3); + + video_redraw(); +} + +#endif/* APPLE_IIE */ + + +/* ------------------------------------------------------------------------- + c_initialize_font(): Initialize ROM character table to primary char set + ------------------------------------------------------------------------- */ +void c_initialize_font() +{ + video_loadfont(0x00,0x40,ucase_glyphs,2); + video_loadfont(0x40,0x40,ucase_glyphs,3); + video_loadfont(0x80,0x40,ucase_glyphs,0); + video_loadfont(0xC0,0x20,ucase_glyphs,0); + video_loadfont(0xE0,0x20,lcase_glyphs,0); + + video_redraw(); +} + + + +/* ------------------------------------------------------------------------- + c_initialize_tables() + ------------------------------------------------------------------------- */ + +void c_initialize_tables() { + + int i; + + pre_compact(); /* Prepare for VM compression */ + + /* reset everything */ + for (i = 0; i < 0x10000; i++) { +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[i].r = iie_read_ram_default; + cpu65_vmem[i].w = iie_write_ram_default; + } else +#endif + { + cpu65_vmem[i].r = read_ram_default; + cpu65_vmem[i].w = write_ram_default; + } + } + + /* language card read/write area */ + for (i = 0xD000; i < 0xE000; i++) { + { + cpu65_vmem[i].w = + write_ram_bank; + cpu65_vmem[i].r = + read_ram_bank; + } + } + for (i = 0xE000; i < 0x10000; i++) { + { + cpu65_vmem[i].w = + write_ram_lc; + cpu65_vmem[i].r = + read_ram_lc; + } + } + /* done common initialization */ + +#ifdef APPLE_IIE + /* initialize zero-page, //e specific */ + if (apple_mode == IIE_MODE) { + for (i = 0; i < 0x200; i++) { + cpu65_vmem[i].r = + iie_read_ram_zpage_and_stack; + cpu65_vmem[i].w = + iie_write_ram_zpage_and_stack; + } + } +#endif + +#ifdef APPLE_IIE + /* initialize first text & hires page, which are specially bank switched + * + * video_set() substitutes it's own hooks for all visible write locations + * affect the display, leaving our write-functions in place only at the + * `screen holes', hence the name. + */ + for (i = 0x400; i < 0x800; i++) { + cpu65_vmem[i].r = + iie_read_ram_text_page0; + cpu65_vmem[i].w = + iie_write_screen_hole_text_page0; + } + for (i = 0x2000; i < 0x4000; i++) { + cpu65_vmem[i].r = + iie_read_ram_hires_page0; + cpu65_vmem[i].w = + iie_write_screen_hole_hires_page0; + } +#endif + + /* softswich rom */ + for (i = 0xC000; i < 0xC100; i++) { + cpu65_vmem[i].r = + read_unmapped_softswitch; + cpu65_vmem[i].w = + write_unmapped_softswitch; + } + + /* slot rom */ + for (i = 0xC100; i < 0xD000; i++) { + cpu65_vmem[i].r = +#ifdef APPLE_IIE + iie_read_ram_default; +#else + read_ram_default; +#endif + cpu65_vmem[i].w = + ram_nop; + } + + /* keyboard data and strobe (READ) */ + for (i = 0xC000; i < 0xC010; i++) { + cpu65_vmem[i].r = + read_keyboard; + } + for (i = 0xC010; i < 0xC020; i++) { + cpu65_vmem[i].r = + cpu65_vmem[i].w = + read_keyboard_strobe; + } + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + + /* RDBNK2 switch */ + cpu65_vmem[0xC011].r = + iie_check_bank; + + /* RDLCRAM switch */ + cpu65_vmem[0xC012].r = + iie_check_lcram; + + /* 80STORE switch */ + cpu65_vmem[0xC000].w = iie_80store_off; + cpu65_vmem[0xC001].w = iie_80store_on; + cpu65_vmem[0xC018].r = iie_check_80store; + + /* RAMRD switch */ + cpu65_vmem[0xC002].w = iie_ramrd_main; + cpu65_vmem[0xC003].w = iie_ramrd_aux; + cpu65_vmem[0xC013].r = iie_check_ramrd; + + /* RAMWRT switch */ + cpu65_vmem[0xC004].w = iie_ramwrt_main; + cpu65_vmem[0xC005].w = iie_ramwrt_aux; + cpu65_vmem[0xC014].r = iie_check_ramwrt; + + /* ALTZP switch */ + cpu65_vmem[0xC008].w = iie_altzp_main; + cpu65_vmem[0xC009].w = iie_altzp_aux; + cpu65_vmem[0xC016].r = iie_check_altzp; + + /* 80COL switch */ + cpu65_vmem[0xC00C].w = iie_80col_off; + cpu65_vmem[0xC00D].w = iie_80col_on; + cpu65_vmem[0xC01F].r = iie_check_80col; + + /* ALTCHAR switch */ + cpu65_vmem[0xC00E].w = iie_altchar_off; + cpu65_vmem[0xC00F].w = iie_altchar_on; + cpu65_vmem[0xC01E].r = iie_check_altchar; + + /* SLOTC3ROM switch */ + cpu65_vmem[0xC00A].w = iie_c3rom_internal; + cpu65_vmem[0xC00B].w = iie_c3rom_peripheral; + cpu65_vmem[0xC017].r = iie_check_c3rom; + + /* SLOTCXROM switch */ + cpu65_vmem[0xC006].w = iie_cxrom_peripheral; + cpu65_vmem[0xC007].w = iie_cxrom_internal; + cpu65_vmem[0xC015].r = iie_check_cxrom; + + /* RDVBLBAR switch */ + cpu65_vmem[0xC019].r = + iie_check_vbl; + } +#endif + + /* random number generator */ + for (i = 0xC020; i < 0xC030; i++) + cpu65_vmem[i].r = + cpu65_vmem[i].w = + read_random; + + /* TEXT switch */ + cpu65_vmem[0xC050].r = + cpu65_vmem[0xC050].w = + read_switch_graphics; + cpu65_vmem[0xC051].r = + cpu65_vmem[0xC051].w = + read_switch_text; + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC01A].r = + iie_check_text; + } +#endif + + /* MIXED switch */ + cpu65_vmem[0xC052].r = + cpu65_vmem[0xC052].w = + read_switch_no_mixed; + cpu65_vmem[0xC053].r = + cpu65_vmem[0xC053].w = + read_switch_mixed; + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC01B].r = + iie_check_mixed; + } + /* PAGE2 switch */ + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC054].r = + cpu65_vmem[0xC054].w = + iie_page2_off; + } else +#endif + { + cpu65_vmem[0xC054].r = + cpu65_vmem[0xC054].w = + read_switch_primary_page; + } + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC01C].r = + iie_check_page2; + } + /* PAGE2 switch */ + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC055].r = + cpu65_vmem[0xC055].w = + iie_page2_on; + } else +#endif + { + cpu65_vmem[0xC055].r = + cpu65_vmem[0xC055].w = + read_switch_secondary_page; + } + + /* HIRES switch */ +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC01D].r = + iie_check_hires; + cpu65_vmem[0xC056].r = + cpu65_vmem[0xC056].w = + iie_hires_off; + cpu65_vmem[0xC057].r = + cpu65_vmem[0xC057].w = + iie_hires_on; + } + else +#endif + { + cpu65_vmem[0xC056].r = + cpu65_vmem[0xC056].w = + read_switch_lores; + cpu65_vmem[0xC057].r = + cpu65_vmem[0xC057].w = + read_switch_hires; + } + + /* game I/O switches */ + cpu65_vmem[0xC061].r = + cpu65_vmem[0xC069].r = + read_button0; + cpu65_vmem[0xC062].r = + cpu65_vmem[0xC06A].r = + read_button1; + cpu65_vmem[0xC063].r = + cpu65_vmem[0xC06B].r = + read_button2; + cpu65_vmem[0xC064].r = + cpu65_vmem[0xC06C].r = + read_gc0; + cpu65_vmem[0xC065].r = + cpu65_vmem[0xC06D].r = + read_gc1; +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[0xC066].r = + iie_read_gc2; + cpu65_vmem[0xC067].r = + iie_read_gc3; + } +#endif + for (i = 0xC070; i < 0xC080; i++) + cpu65_vmem[i].r = + cpu65_vmem[i].w = + read_gc_strobe; + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + /* IOUDIS switch & read_gc_strobe */ + cpu65_vmem[0xC07E].w = + iie_ioudis_on; + cpu65_vmem[0xC07F].w = + iie_ioudis_off; + cpu65_vmem[0xC07E].r = + iie_check_ioudis; + cpu65_vmem[0xC07F].r = + iie_check_dhires; + + /* DHIRES/Annunciator switches */ + cpu65_vmem[0xC05E].w = + cpu65_vmem[0xC05E].r = + iie_dhires_on; + cpu65_vmem[0xC05F].w = + cpu65_vmem[0xC05F].r = + iie_dhires_off; + } +#endif + +#ifdef APPLE_IIE + /* language card softswitches */ + cpu65_vmem[0xC080].r = cpu65_vmem[0xC080].w = + cpu65_vmem[0xC084].r = cpu65_vmem[0xC084].w = + (apple_mode == IIE_MODE) ? iie_c080 : lc_c080; + cpu65_vmem[0xC081].r = cpu65_vmem[0xC081].w = + cpu65_vmem[0xC085].r = cpu65_vmem[0xC085].w = + (apple_mode == IIE_MODE) ? iie_c081 : lc_c081; + cpu65_vmem[0xC082].r = cpu65_vmem[0xC082].w = + cpu65_vmem[0xC086].r = cpu65_vmem[0xC086].w = + lc_c082; + cpu65_vmem[0xC083].r = cpu65_vmem[0xC083].w = + cpu65_vmem[0xC087].r = cpu65_vmem[0xC087].w = + (apple_mode == IIE_MODE) ? iie_c083 : lc_c083; + + cpu65_vmem[0xC088].r = cpu65_vmem[0xC088].w = + cpu65_vmem[0xC08C].r = cpu65_vmem[0xC08C].w = + (apple_mode == IIE_MODE) ? iie_c088 : lc_c088; + cpu65_vmem[0xC089].r = cpu65_vmem[0xC089].w = + cpu65_vmem[0xC08D].r = cpu65_vmem[0xC08D].w = + (apple_mode == IIE_MODE) ? iie_c089 : lc_c089; + cpu65_vmem[0xC08A].r = cpu65_vmem[0xC08A].w = + cpu65_vmem[0xC08E].r = cpu65_vmem[0xC08E].w = + lc_c08a; + cpu65_vmem[0xC08B].r = cpu65_vmem[0xC08B].w = + cpu65_vmem[0xC08F].r = cpu65_vmem[0xC08F].w = + (apple_mode == IIE_MODE) ? iie_c08b : lc_c08b; +#else /* !APPLE_IIE */ + /* language card softswitches */ + cpu65_vmem[0xC080].r = cpu65_vmem[0xC080].w = + cpu65_vmem[0xC084].r = cpu65_vmem[0xC084].w = + lc_c080; + cpu65_vmem[0xC081].r = cpu65_vmem[0xC081].w = + cpu65_vmem[0xC085].r = cpu65_vmem[0xC085].w = + lc_c081; + cpu65_vmem[0xC082].r = cpu65_vmem[0xC082].w = + cpu65_vmem[0xC086].r = cpu65_vmem[0xC086].w = + lc_c082; + cpu65_vmem[0xC083].r = cpu65_vmem[0xC083].w = + cpu65_vmem[0xC087].r = cpu65_vmem[0xC087].w = + lc_c083; + + cpu65_vmem[0xC088].r = cpu65_vmem[0xC088].w = + cpu65_vmem[0xC08C].r = cpu65_vmem[0xC08C].w = + lc_c088; + cpu65_vmem[0xC089].r = cpu65_vmem[0xC089].w = + cpu65_vmem[0xC08D].r = cpu65_vmem[0xC08D].w = + lc_c089; + cpu65_vmem[0xC08A].r = cpu65_vmem[0xC08A].w = + cpu65_vmem[0xC08E].r = cpu65_vmem[0xC08E].w = + lc_c08a; + cpu65_vmem[0xC08B].r = cpu65_vmem[0xC08B].w = + cpu65_vmem[0xC08F].r = cpu65_vmem[0xC08F].w = + lc_c08b; +#endif /* !APPLE_IIE */ + +#ifdef APPLE_IIE + /* slot i/o area */ + for (i = 0xC100; i < 0xC300; i++) { + cpu65_vmem[i].r = + iie_read_slotx; /* slots 1 & 2 (x) */ + } + for (i = 0xC300; i < 0xC400; i++) { + cpu65_vmem[i].r = + iie_read_slot3; /* slot 3 (80col) */ + } + for (i = 0xC400; i < 0xC800; i++) { + cpu65_vmem[i].r = + iie_read_slotx; /* slots 4 - 7 (x) */ + } + for (i = 0xC800; i < 0xD000; i++) { + cpu65_vmem[i].r = + iie_read_slot_expansion; /* expansion rom */ + } + cpu65_vmem[0xCFFF].r = + cpu65_vmem[0xCFFF].w = + iie_disable_slot_expansion; +#endif + + video_set(0); /* must be done here, between pre_compact & compact */ + + disk_install(6); /* Put a Disk ][ Controller in slot 6 */ + + compact(); /* Compress memory so that identical pages share storage */ + +} + +/* ------------------------------------------------------------------------- + c_initialize_apple_ii_memory() + ------------------------------------------------------------------------- */ + +void c_initialize_apple_ii_memory() +{ + FILE *f; + int i; + static int ii_rom_loaded = 0; +#ifdef APPLE_IIE + static int iie_rom_loaded = 0; +#endif + + for (i = 0; i < 0x10000; i++) { + apple_ii_64k[0][i] = 0; + apple_ii_64k[1][i] = 0; + } + for (i = 0; i < 8192; i++) + language_card[0][i] = language_card[1][i] = 0; + for (i = 0; i < 8192; i++) + language_banks[0][i] = language_banks[1][i] = 0; + + if (!ii_rom_loaded) + { + snprintf(temp, TEMPSIZE, "%s/apple_II.rom", system_path); + if ((f = fopen(temp, "r")) == NULL) { + printf("OOPS!\n"); + printf("Cannot find file '%s'.\n",temp); + exit(0); + } + fread(apple_ii_rom, 0x3000, 1, f); + fclose(f); + ii_rom_loaded = 1; + } + +#ifdef APPLE_IIE + if (!iie_rom_loaded) { + snprintf(temp, TEMPSIZE, "%s/apple_IIe.rom", system_path); + if ((f = fopen(temp, "r")) == NULL) { + printf("Cannot find file '%s'.\n",temp); + exit(0); + } + fread(apple_iie_rom, 32768, 1, f); + fclose(f); + iie_rom_loaded = 1; + } +#endif + + for (i = 0xD000; i < 0x10000; i++) + apple_ii_64k[0][i] = apple_ii_rom[i - 0xD000]; + for (i = 0; i < 0x1000; i++) + language_banks[0][i] = apple_ii_rom[i]; + for (i = 0; i < 0x2000; i++) + language_card[0][i] = apple_ii_rom[i + 0x1000]; + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + /* load the rom from 0xC000, slot rom main, internal rom aux */ + for (i = 0xC000; i < 0x10000; i++) { + apple_ii_64k[0][i] = apple_iie_rom[i - 0xC000]; + apple_ii_64k[1][i] = apple_iie_rom[i - 0x8000]; + } + for (i = 0; i < 0x1000; i++) { + language_banks[0][i] = apple_iie_rom[i + 0x1000]; + language_banks[1][i] = apple_iie_rom[i + 0x5000]; + } + for (i = 0; i < 0x2000; i++) { + language_card[0][i] = apple_iie_rom[i + 0x2000]; + language_card[1][i] = apple_iie_rom[i + 0x6000]; + } + } + else +#endif + /* softswitch memory HACK - why this? */ + { + for (i = 0xC100; i < 0xD000; i++) { + apple_ii_64k[0][i] = i & 0xFF; + apple_ii_64k[1][i] = i & 0xFF; + } + } + + apple_ii_64k[0][0xC000] = 0x00; + apple_ii_64k[1][0xC000] = 0x00; +} + +/* ------------------------------------------------------------------------- + void c_initialize_sound() + ------------------------------------------------------------------------- */ + +void c_initialize_sound() +{ + int i; + + for (i = 0xC030; i < 0xC040; i++) + cpu65_vmem[i].r = cpu65_vmem[i].w = + (sound_mode && soundAllowed) ? read_speaker_toggle_pc : ram_nop; +} + +#ifdef APPLE_IIE +/* ------------------------------------------------------------------------- + c_initialize_iie_switches + ------------------------------------------------------------------------- */ +void c_initialize_iie_switches() { + + base_stackzp = apple_ii_64k[0]; + base_d000_rd = apple_ii_64k[0]; + base_d000_wrt = language_banks[0] - 0xD000; + base_e000_rd = apple_ii_64k[0]; + base_e000_wrt = language_card[0] - 0xE000; + + base_ramrd = apple_ii_64k[0]; + base_ramwrt = apple_ii_64k[0]; + base_textrd = apple_ii_64k[0]; + base_textwrt = apple_ii_64k[0]; + base_hgrrd = apple_ii_64k[0]; + base_hgrwrt= apple_ii_64k[0]; + + base_c3rom = apple_ii_64k[1]; /* c3rom internal */ + c8rom_offset = 0x10000; /* c8rom internal */ + base_cxrom = apple_ii_64k[0]; /* cxrom peripheral */ +} +#endif + +/* ------------------------------------------------------------------------- + void c_initialize_vm() + ------------------------------------------------------------------------- */ +void c_initialize_vm() { + c_initialize_font(); /* font already read in */ + c_initialize_apple_ii_memory(); /* read in rom memory */ + c_initialize_tables(); /* read/write memory jump tables */ + c_initialize_sound(); /* sound system */ + c_init_6(); /* drive ][, slot 6 */ + +#ifdef APPLE_IIE + c_initialize_iie_switches(); /* set the //e softswitches */ +#endif + +#ifdef MOUSE_EMULATION + c_initialize_mouse(); +#endif +} + +/* ------------------------------------------------------------------------- + void c_initialize_firsttime() + ------------------------------------------------------------------------- */ + +static void reinitialize(void) +{ + int i; + +#ifdef DEBUGGER + /* reset the watchpoints and breakpoints */ + for (i=0; i> 8); +} + +int main(int sargc, char *sargv[]) +{ + int i; + + argc = sargc; + argv = sargv; + + for (i = 1; i < argc; i++) + { +/* + if (strcmp(argv[i], "-vga") == 0) + force_vga_mode = 1; +*/ + } + + load_settings(); /* user prefs */ + c_initialize_firsttime(); /* init svga graphics and vm */ + + for (;;) { + /* execute the emulator */ + cpu65_run(); + + reinitialize(); + } + /* never reached */ +} diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 00000000..5484d313 --- /dev/null +++ b/src/misc.h @@ -0,0 +1,261 @@ +/* + * Apple // emulator for Linux: Miscellaneous defines + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef MISC_H +#define MISC_H + +#ifndef __ASSEMBLER__ + +#include +#include + +#define SW_TEXT 0xC050 +#define SW_MIXED 0xC052 +#define SW_PAGE2 0xC054 +#define SW_HIRES 0xC056 +#ifdef APPLE_IIE +#define SW_80STORE 0xC000 +#define SW_RAMRD 0xC002 +#define SW_RAMWRT 0xC004 +#define SW_ALTZP 0xC008 +#define SW_80COL 0xC00C +#define SW_ALTCHAR 0xC00E +#define SW_SLOTC3ROM 0xC00B /* anomaly */ +#define SW_SLOTCXROM 0xC006 +#define SW_DHIRES 0xC05E +#define SW_IOUDIS 0xC07E +#endif + +extern const struct itimerval timer_on,timer_off; + +/* Text characters */ +extern const unsigned char ucase_glyphs[0x200]; +extern const unsigned char lcase_glyphs[0x100]; +extern const unsigned char mousetext_glyphs[0x100]; +extern const unsigned char interface_glyphs[88]; + +unsigned char apple_ii_64k[2][65536]; /* 128k memory */ + +/* language card memory and settings */ +unsigned char language_card[2][8192], language_banks[2][8192]; + +/* misc stuff */ +int soundAllowed; +unsigned char random_value; + +/* global ref to commandline args */ +char **argv; +int argc; + +/* misc arrays */ +#define TEMPSIZE 4096 +unsigned char temp[ TEMPSIZE ];/* should be >=4096 (stuff depends on this) */ + +#ifdef APPLE_IIE +/* memory offsets from softswitches */ +int c8rom_offset; + +extern unsigned char *base_ramrd; +extern unsigned char *base_ramwrt; +extern unsigned char *base_textrd; +extern unsigned char *base_textwrt; +extern unsigned char *base_hgrrd; +extern unsigned char *base_hgrwrt; + +extern unsigned char *base_stackzp; +extern unsigned char *base_d000_rd; +extern unsigned char *base_e000_rd; +extern unsigned char *base_d000_wrt; +extern unsigned char *base_e000_wrt; + +extern unsigned char *base_c3rom; +extern unsigned char *base_cxrom; + +#endif /* APPLE_IIE */ + +/* softswitches */ + +extern int softswitches; + +#endif /* !__ASSEMBLER__ */ + +#define SS_TEXT 0x00000001 +#define SS_MIXED 0x00000002 +#define SS_HIRES 0x00000004 +#define SS_PAGE2 0x00000008 +#define SS_BANK2 0x00000010 +#define SS_LCRAM 0x00000020 +#define SS_LCSEC 0x00000040 /* check for double read */ +#define SS_LCWRT 0x00000080 /* LC write enable */ +#define SS_80STORE 0x00000100 +#define SS_80COL 0x00000200 +#define SS_RAMRD 0x00000400 +#define SS_RAMWRT 0x00000800 +#define SS_ALTZP 0x00001000 +#define SS_DHIRES 0x00002000 +#define SS_IOUDIS 0x00004000 +#define SS_CXROM 0x00008000 +#define SS_C3ROM 0x00010000 +#define SS_ALTCHAR 0x00020000 + +/* Pseudo soft switches. These are actually functions of other SSes, but are + * tiresome to calculate as needed. + * + */ +#define SS_SCREEN 0x00040000 /* PAGE2 && !80STORE */ +#define SS_TEXTRD 0x00080000 /* (PAGE2 && 80STORE) || + (RAMRD && !80STORE) */ +#define SS_TEXTWRT 0x00100000 /* (PAGE2 && 80STORE) || + (RAMWRT && !80STORE) */ +#define SS_HGRRD 0x00200000 /* (PAGE2 && 80STORE && HIRES) || + (RAMRD && !(80STORE && HIRES) */ +#define SS_HGRWRT 0x00400000 /* (PAGE2 && 80STORE && HIRES) || + (RAMWRT && !(80STORE && HIRES)) */ + +#ifndef __ASSEMBLER__ +/* ------------------------------------------------------------------------- + misc.c functions + ------------------------------------------------------------------------- */ + +void c_initialize_sound(); +void c_initialize_font(); +void c_initialize_vm(); +void c_read_random(); + +/* virtual memory compacter */ + +void pre_compact(void); +void compact(void); + +/* vm hooks */ + +void ram_nop(), + + write_ram_default(), + write_unmapped_softswitch(), + + read_ram_default(), + read_random(), + read_unmapped_softswitch(), + read_keyboard(), + read_keyboard_strobe(), + read_speaker_toggle_pc(), + read_switch_primary_page(), + read_switch_secondary_page(), + read_switch_graphics(), + read_switch_text(), + read_switch_no_mixed(), + read_switch_mixed(), + read_switch_lores(), + read_switch_hires(), + + read_button0(), + read_button1(), + read_button2(), + read_gc0(), + read_gc1(), + read_gc_strobe(), + + lc_c080(), + lc_c081(), + lc_c082(), + lc_c083(), + lc_c088(), + lc_c089(), + lc_c08a(), + lc_c08b(), + write_ram_bank(), + read_ram_bank(), + write_ram_lc(), + read_ram_lc(); + +#ifdef APPLE_IIE +void iie_write_ram_default(), + iie_read_ram_default(), + + /* //e text pages */ + iie_read_ram_text_page0(), + iie_write_screen_hole_text_page0(), + + /* //e hires page 0 */ + iie_read_ram_hires_page0(), + iie_write_screen_hole_hires_page0(), + + /* //e zpage,stack, ram banks */ + iie_read_ram_zpage_and_stack(), + iie_write_ram_zpage_and_stack(), + iie_read_slot3(), + iie_read_slotx(), + iie_read_slot_expansion(), + iie_disable_slot_expansion(), + iie_read_gc2(), + iie_read_gc3(), + + iie_c080(), + iie_c081(), + iie_c083(), + iie_c088(), + iie_c089(), + iie_c08b(), + + /* //e toggle softswitches */ + iie_ramrd_main(), + iie_ramrd_aux(), + iie_ramwrt_main(), + iie_ramwrt_aux(), + iie_80store_off(), + iie_80store_on(), + iie_altzp_main(), + iie_altzp_aux(), + iie_80col_off(), + iie_80col_on(), + iie_altchar_off(), + iie_altchar_on(), + iie_c3rom_peripheral(), + iie_c3rom_internal(), + iie_cxrom_peripheral(), + iie_cxrom_internal(), + iie_ioudis_on(), + iie_ioudis_off(), + iie_dhires_on(), + iie_dhires_off(), + iie_hires_off(), + iie_hires_on(), + iie_page2_on(), + iie_page2_off(), + + /* //e check softswitche settings */ + iie_check_80store(), + iie_check_bank(), + iie_check_lcram(), + iie_check_ramrd(), + iie_check_ramwrt(), + iie_check_altzp(), + iie_check_c3rom(), + iie_check_cxrom(), + iie_check_80col(), + iie_check_altchar(), + iie_check_text(), + iie_check_mixed(), + iie_check_hires(), + iie_check_page2(), + iie_check_ioudis(), + iie_check_dhires(), + iie_check_vbl(); +#endif /* APPLE_IIE */ +#endif /* !__ASSEMBLER__ */ + +#endif diff --git a/src/opcodes.c b/src/opcodes.c new file mode 100644 index 00000000..e38cf508 --- /dev/null +++ b/src/opcodes.c @@ -0,0 +1,820 @@ +/* + * Apple // emulator for Linux: Opcode tables for debugger + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include "debug.h" + +const char * const disasm_templates[15] = +{ + "", + "A", + "#$%02X", + "$%02X", + "$%02X,X", + "$%02X,Y", + "$%02X%02X", + "$%02X%02X,X", + "$%02X%02X,Y", + "($%02X)", + "($%02X,X)", + "($%02X),Y", + "($%02X%02X)", + "($%02X%02X),X", + "$%04X (%c%02X)" +}; + +const struct opcode_struct opcodes_6502[256] = +{ + {"BRK", addr_implied}, + {"ORA", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ORA", addr_zeropage}, + {"ASL", addr_zeropage}, + {"???", addr_implied}, + {"PHP", addr_implied}, + {"ORA", addr_immediate}, + {"ASL", addr_accumulator}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ORA", addr_absolute}, + {"ASL", addr_absolute}, + {"???", addr_implied}, + {"BPL", addr_relative}, + {"ORA", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ORA", addr_zeropage_x}, + {"ASL", addr_zeropage_x}, + {"???", addr_implied}, + {"CLC", addr_implied}, + {"ORA", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ORA", addr_absolute_x}, + {"ASL", addr_absolute_x}, + {"???", addr_implied}, + {"JSR", addr_absolute}, + {"AND", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"BIT", addr_zeropage}, + {"AND", addr_zeropage}, + {"ROL", addr_zeropage}, + {"???", addr_implied}, + {"PLP", addr_implied}, + {"AND", addr_immediate}, + {"ROL", addr_accumulator}, + {"???", addr_implied}, + {"BIT", addr_absolute}, + {"AND", addr_absolute}, + {"ROL", addr_absolute}, + {"???", addr_implied}, + {"BMI", addr_relative}, + {"AND", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"AND", addr_zeropage_x}, + {"ROL", addr_zeropage_x}, + {"???", addr_implied}, + {"SEC", addr_implied}, + {"AND", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"AND", addr_absolute_x}, + {"ROL", addr_absolute_x}, + {"???", addr_implied}, + {"RTI", addr_implied}, + {"EOR", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_zeropage}, + {"LSR", addr_zeropage}, + {"???", addr_implied}, + {"PHA", addr_implied}, + {"EOR", addr_immediate}, + {"LSR", addr_accumulator}, + {"???", addr_implied}, + {"JMP", addr_absolute}, + {"EOR", addr_absolute}, + {"LSR", addr_absolute}, + {"???", addr_implied}, + {"BVC", addr_relative}, + {"EOR", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_zeropage_x}, + {"LSR", addr_zeropage_x}, + {"???", addr_implied}, + {"CLI", addr_implied}, + {"EOR", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_absolute_x}, + {"LSR", addr_absolute_x}, + {"???", addr_implied}, + {"RTS", addr_implied}, + {"ADC", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ADC", addr_zeropage}, + {"ROR", addr_zeropage}, + {"???", addr_implied}, + {"PLA", addr_implied}, + {"ADC", addr_immediate}, + {"ROR", addr_accumulator}, + {"???", addr_implied}, + {"JMP", addr_j_indirect}, + {"ADC", addr_absolute}, + {"ROR", addr_absolute}, + {"???", addr_implied}, + {"BVS", addr_relative}, + {"ADC", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ADC", addr_zeropage_x}, + {"ROR", addr_zeropage_x}, + {"???", addr_implied}, + {"SEI", addr_implied}, + {"ADC", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"ADC", addr_absolute_x}, + {"ROR", addr_absolute_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STA", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STY", addr_zeropage}, + {"STA", addr_zeropage}, + {"STX", addr_zeropage}, + {"???", addr_implied}, + {"DEY", addr_implied}, + {"???", addr_implied}, + {"TXA", addr_implied}, + {"???", addr_implied}, + {"STY", addr_absolute}, + {"STA", addr_absolute}, + {"STX", addr_absolute}, + {"???", addr_implied}, + {"BCC", addr_relative}, + {"STA", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STY", addr_zeropage_x}, + {"STA", addr_zeropage_x}, + {"STX", addr_zeropage_y}, + {"???", addr_implied}, + {"TYA", addr_implied}, + {"STA", addr_absolute_y}, + {"TXS", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STA", addr_absolute_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_immediate}, + {"LDA", addr_indirect_x}, + {"LDX", addr_immediate}, + {"???", addr_implied}, + {"LDY", addr_zeropage}, + {"LDA", addr_zeropage}, + {"LDX", addr_zeropage}, + {"???", addr_implied}, + {"TAY", addr_implied}, + {"LDA", addr_immediate}, + {"TAX", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_absolute}, + {"LDA", addr_absolute}, + {"LDX", addr_absolute}, + {"???", addr_implied}, + {"BCS", addr_relative}, + {"LDA", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_zeropage_x}, + {"LDA", addr_zeropage_x}, + {"LDX", addr_zeropage_y}, + {"???", addr_implied}, + {"CLV", addr_implied}, + {"LDA", addr_absolute_y}, + {"TSX", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_absolute_x}, + {"LDA", addr_absolute_x}, + {"LDX", addr_absolute_y}, + {"???", addr_implied}, + {"CPY", addr_immediate}, + {"CMP", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CPY", addr_zeropage}, + {"CMP", addr_zeropage}, + {"DEC", addr_zeropage}, + {"???", addr_implied}, + {"INY", addr_implied}, + {"CMP", addr_immediate}, + {"DEX", addr_implied}, + {"???", addr_implied}, + {"CPY", addr_absolute}, + {"CMP", addr_absolute}, + {"DEC", addr_absolute}, + {"???", addr_implied}, + {"BNE", addr_relative}, + {"CMP", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CMP", addr_zeropage_x}, + {"DEC", addr_zeropage_x}, + {"???", addr_implied}, + {"CLD", addr_implied}, + {"CMP", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CMP", addr_absolute_x}, + {"DEC", addr_absolute_x}, + {"???", addr_implied}, + {"CPX", addr_immediate}, + {"SBC", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CPX", addr_zeropage}, + {"SBC", addr_zeropage}, + {"INC", addr_zeropage}, + {"???", addr_implied}, + {"INX", addr_implied}, + {"SBC", addr_immediate}, + {"NOP", addr_implied}, + {"???", addr_implied}, + {"CPX", addr_absolute}, + {"SBC", addr_absolute}, + {"INC", addr_absolute}, + {"???", addr_implied}, + {"BEQ", addr_relative}, + {"SBC", addr_indirect_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"SBC", addr_zeropage_x}, + {"INC", addr_zeropage_x}, + {"???", addr_implied}, + {"SED", addr_implied}, + {"SBC", addr_absolute_y}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"SBC", addr_absolute_x}, + {"INC", addr_absolute_x}, + {"???", addr_implied}, +}; + +#ifdef APPLE_IIE + +const struct opcode_struct opcodes_65c02[256] = +{ + {"BRK", addr_implied}, + {"ORA", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"TSB", addr_zeropage}, + {"ORA", addr_zeropage}, + {"ASL", addr_zeropage}, + {"???", addr_implied}, + {"PHP", addr_implied}, + {"ORA", addr_immediate}, + {"ASL", addr_accumulator}, + {"???", addr_implied}, + {"TSB", addr_absolute}, + {"ORA", addr_absolute}, + {"ASL", addr_absolute}, + {"???", addr_implied}, + {"BPL", addr_relative}, + {"ORA", addr_indirect_y}, + {"ORA", addr_indirect}, + {"???", addr_implied}, + {"TRB", addr_zeropage}, + {"ORA", addr_zeropage_x}, + {"ASL", addr_zeropage_x}, + {"???", addr_implied}, + {"CLC", addr_implied}, + {"ORA", addr_absolute_y}, + {"INC", addr_accumulator}, + {"???", addr_implied}, + {"TRB", addr_absolute}, + {"ORA", addr_absolute_x}, + {"ASL", addr_absolute_x}, + {"???", addr_implied}, + {"JSR", addr_absolute}, + {"AND", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"BIT", addr_zeropage}, + {"AND", addr_zeropage}, + {"ROL", addr_zeropage}, + {"???", addr_implied}, + {"PLP", addr_implied}, + {"AND", addr_immediate}, + {"ROL", addr_accumulator}, + {"???", addr_implied}, + {"BIT", addr_absolute}, + {"AND", addr_absolute}, + {"ROL", addr_absolute}, + {"???", addr_implied}, + {"BMI", addr_relative}, + {"AND", addr_indirect_y}, + {"AND", addr_indirect}, + {"???", addr_implied}, + {"BIT", addr_zeropage_x}, + {"AND", addr_zeropage_x}, + {"ROL", addr_zeropage_x}, + {"???", addr_implied}, + {"SEC", addr_implied}, + {"AND", addr_absolute_y}, + {"DEC", addr_accumulator}, + {"???", addr_implied}, + {"BIT", addr_absolute_x}, + {"AND", addr_absolute_x}, + {"ROL", addr_absolute_x}, + {"???", addr_implied}, + {"RTI", addr_implied}, + {"EOR", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_zeropage}, + {"LSR", addr_zeropage}, + {"???", addr_implied}, + {"PHA", addr_implied}, + {"EOR", addr_immediate}, + {"LSR", addr_accumulator}, + {"???", addr_implied}, + {"JMP", addr_absolute}, + {"EOR", addr_absolute}, + {"LSR", addr_absolute}, + {"???", addr_implied}, + {"BVC", addr_relative}, + {"EOR", addr_indirect_y}, + {"EOR", addr_indirect}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_zeropage_x}, + {"LSR", addr_zeropage_x}, + {"???", addr_implied}, + {"CLI", addr_implied}, + {"EOR", addr_absolute_y}, + {"PHY", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"EOR", addr_absolute_x}, + {"LSR", addr_absolute_x}, + {"???", addr_implied}, + {"RTS", addr_implied}, + {"ADC", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STZ", addr_zeropage}, + {"ADC", addr_zeropage}, + {"ROR", addr_zeropage}, + {"???", addr_implied}, + {"PLA", addr_implied}, + {"ADC", addr_immediate}, + {"ROR", addr_accumulator}, + {"???", addr_implied}, + {"JMP", addr_j_indirect}, + {"ADC", addr_absolute}, + {"ROR", addr_absolute}, + {"???", addr_implied}, + {"BVS", addr_relative}, + {"ADC", addr_indirect_y}, + {"ADC", addr_indirect}, + {"???", addr_implied}, + {"STZ", addr_zeropage_x}, + {"ADC", addr_zeropage_x}, + {"ROR", addr_zeropage_x}, + {"???", addr_implied}, + {"SEI", addr_implied}, + {"ADC", addr_absolute_y}, + {"PLY", addr_implied}, + {"???", addr_implied}, + {"JMP", addr_j_indirect_x}, + {"ADC", addr_absolute_x}, + {"ROR", addr_absolute_x}, + {"???", addr_implied}, + {"BRA", addr_relative}, + {"STA", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"STY", addr_zeropage}, + {"STA", addr_zeropage}, + {"STX", addr_zeropage}, + {"???", addr_implied}, + {"DEY", addr_implied}, + {"BIT", addr_immediate}, + {"TXA", addr_implied}, + {"???", addr_implied}, + {"STY", addr_absolute}, + {"STA", addr_absolute}, + {"STX", addr_absolute}, + {"???", addr_implied}, + {"BCC", addr_relative}, + {"STA", addr_indirect_y}, + {"STA", addr_indirect}, + {"???", addr_implied}, + {"STY", addr_zeropage_x}, + {"STA", addr_zeropage_x}, + {"STX", addr_zeropage_y}, + {"???", addr_implied}, + {"TYA", addr_implied}, + {"STA", addr_absolute_y}, + {"TXS", addr_implied}, + {"???", addr_implied}, + {"STZ", addr_absolute}, + {"STA", addr_absolute_x}, + {"STZ", addr_absolute_x}, + {"???", addr_implied}, + {"LDY", addr_immediate}, + {"LDA", addr_indirect_x}, + {"LDX", addr_immediate}, + {"???", addr_implied}, + {"LDY", addr_zeropage}, + {"LDA", addr_zeropage}, + {"LDX", addr_zeropage}, + {"???", addr_implied}, + {"TAY", addr_implied}, + {"LDA", addr_immediate}, + {"TAX", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_absolute}, + {"LDA", addr_absolute}, + {"LDX", addr_absolute}, + {"???", addr_implied}, + {"BCS", addr_relative}, + {"LDA", addr_indirect_y}, + {"LDA", addr_indirect}, + {"???", addr_implied}, + {"LDY", addr_zeropage_x}, + {"LDA", addr_zeropage_x}, + {"LDX", addr_zeropage_y}, + {"???", addr_implied}, + {"CLV", addr_implied}, + {"LDA", addr_absolute_y}, + {"TSX", addr_implied}, + {"???", addr_implied}, + {"LDY", addr_absolute_x}, + {"LDA", addr_absolute_x}, + {"LDX", addr_absolute_y}, + {"???", addr_implied}, + {"CPY", addr_immediate}, + {"CMP", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CPY", addr_zeropage}, + {"CMP", addr_zeropage}, + {"DEC", addr_zeropage}, + {"???", addr_implied}, + {"INY", addr_implied}, + {"CMP", addr_immediate}, + {"DEX", addr_implied}, + {"???", addr_implied}, + {"CPY", addr_absolute}, + {"CMP", addr_absolute}, + {"DEC", addr_absolute}, + {"???", addr_implied}, + {"BNE", addr_relative}, + {"CMP", addr_indirect_y}, + {"CMP", addr_indirect}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CMP", addr_zeropage_x}, + {"DEC", addr_zeropage_x}, + {"???", addr_implied}, + {"CLD", addr_implied}, + {"CMP", addr_absolute_y}, + {"PHX", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CMP", addr_absolute_x}, + {"DEC", addr_absolute_x}, + {"???", addr_implied}, + {"CPX", addr_immediate}, + {"SBC", addr_indirect_x}, + {"???", addr_implied}, + {"???", addr_implied}, + {"CPX", addr_zeropage}, + {"SBC", addr_zeropage}, + {"INC", addr_zeropage}, + {"???", addr_implied}, + {"INX", addr_implied}, + {"SBC", addr_immediate}, + {"NOP", addr_implied}, + {"???", addr_implied}, + {"CPX", addr_absolute}, + {"SBC", addr_absolute}, + {"INC", addr_absolute}, + {"???", addr_implied}, + {"BEQ", addr_relative}, + {"SBC", addr_indirect_y}, + {"SBC", addr_indirect}, + {"???", addr_implied}, + {"???", addr_implied}, + {"SBC", addr_zeropage_x}, + {"INC", addr_zeropage_x}, + {"???", addr_implied}, + {"SED", addr_implied}, + {"SBC", addr_absolute_y}, + {"PLX", addr_implied}, + {"???", addr_implied}, + {"???", addr_implied}, + {"SBC", addr_absolute_x}, + {"INC", addr_absolute_x}, + {"???", addr_implied}, +}; + +#endif /* APPLE_IIE */ + +const struct opcode_struct opcodes_undoc[256] = +{ + {"BRK", addr_implied}, + {"ORA", addr_indirect_x}, + {"hang", addr_implied}, + {"lor", addr_indirect_x}, + {"nop", addr_zeropage}, + {"ORA", addr_zeropage}, + {"ASL", addr_zeropage}, + {"lor", addr_zeropage}, + {"PHP", addr_implied}, + {"ORA", addr_immediate}, + {"ASL", addr_accumulator}, + {"ana", addr_immediate}, + {"nop", addr_absolute}, + {"ORA", addr_absolute}, + {"ASL", addr_absolute}, + {"lor", addr_absolute}, + {"BPL", addr_relative}, + {"ORA", addr_indirect_y}, + {"hang", addr_implied}, + {"lor", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"ORA", addr_zeropage_x}, + {"ASL", addr_zeropage_x}, + {"lor", addr_zeropage_x}, + {"CLC", addr_implied}, + {"ORA", addr_absolute_y}, + {"nop", addr_implied}, + {"lor", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"ORA", addr_absolute_x}, + {"ASL", addr_absolute_x}, + {"lor", addr_absolute}, + {"JSR", addr_absolute}, + {"AND", addr_indirect_x}, + {"hang", addr_implied}, + {"lan", addr_indirect_x}, + {"BIT", addr_zeropage}, + {"AND", addr_zeropage}, + {"ROL", addr_zeropage}, + {"lan", addr_zeropage}, + {"PLP", addr_implied}, + {"AND", addr_immediate}, + {"ROL", addr_accumulator}, + {"anb", addr_immediate}, + {"BIT", addr_absolute}, + {"AND", addr_absolute}, + {"ROL", addr_absolute}, + {"lan", addr_absolute}, + {"BMI", addr_relative}, + {"AND", addr_indirect_y}, + {"hang", addr_implied}, + {"lan", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"AND", addr_zeropage_x}, + {"ROL", addr_zeropage_x}, + {"lan", addr_zeropage_x}, + {"SEC", addr_implied}, + {"AND", addr_absolute_y}, + {"nop", addr_implied}, + {"lan", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"AND", addr_absolute_x}, + {"ROL", addr_absolute_x}, + {"lan", addr_absolute_x}, + {"RTI", addr_implied}, + {"EOR", addr_indirect_x}, + {"hang", addr_implied}, + {"reo", addr_indirect_x}, + {"nop", addr_zeropage}, + {"EOR", addr_zeropage}, + {"LSR", addr_zeropage}, + {"reo", addr_zeropage}, + {"PHA", addr_implied}, + {"EOR", addr_immediate}, + {"LSR", addr_accumulator}, + {"ram", addr_immediate}, + {"JMP", addr_absolute}, + {"EOR", addr_absolute}, + {"LSR", addr_absolute}, + {"reo", addr_absolute}, + {"BVC", addr_relative}, + {"EOR", addr_indirect_y}, + {"hang", addr_implied}, + {"reo", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"EOR", addr_zeropage_x}, + {"LSR", addr_zeropage_x}, + {"reo", addr_zeropage_x}, + {"CLI", addr_implied}, + {"EOR", addr_absolute_y}, + {"nop", addr_implied}, + {"reo", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"EOR", addr_absolute_x}, + {"LSR", addr_absolute_x}, + {"reo", addr_absolute_x}, + {"RTS", addr_implied}, + {"ADC", addr_indirect_x}, + {"hang", addr_implied}, + {"rad", addr_indirect_x}, + {"nop", addr_zeropage}, + {"ADC", addr_zeropage}, + {"ROR", addr_zeropage}, + {"rad", addr_zeropage}, + {"PLA", addr_implied}, + {"ADC", addr_immediate}, + {"ROR", addr_accumulator}, + {"rbm", addr_immediate}, + {"JMP", addr_j_indirect}, + {"ADC", addr_absolute}, + {"ROR", addr_absolute}, + {"rad", addr_absolute}, + {"BVS", addr_relative}, + {"ADC", addr_indirect_y}, + {"hang", addr_implied}, + {"rad", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"ADC", addr_zeropage_x}, + {"ROR", addr_zeropage_x}, + {"rad", addr_zeropage_x}, + {"SEI", addr_implied}, + {"ADC", addr_absolute_y}, + {"nop", addr_implied}, + {"rad", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"ADC", addr_absolute_x}, + {"ROR", addr_absolute_x}, + {"rad", addr_absolute_x}, + {"nop", addr_immediate}, + {"STA", addr_indirect_x}, + {"nop", addr_immediate}, + {"aax", addr_indirect_x}, + {"STY", addr_zeropage}, + {"STA", addr_zeropage}, + {"STX", addr_zeropage}, + {"aax", addr_zeropage}, + {"DEY", addr_implied}, + {"nop", addr_immediate}, + {"TXA", addr_implied}, + {"xma", addr_immediate}, + {"STY", addr_absolute}, + {"STA", addr_absolute}, + {"STX", addr_absolute}, + {"aax", addr_absolute}, + {"BCC", addr_relative}, + {"STA", addr_indirect_y}, + {"hang", addr_implied}, + {"aax", addr_indirect_y}, + {"STY", addr_zeropage_x}, + {"STA", addr_zeropage_x}, + {"STX", addr_zeropage_y}, + {"aax", addr_zeropage_y}, + {"TYA", addr_implied}, + {"STA", addr_absolute_y}, + {"TXS", addr_implied}, + {"axs", addr_absolute_y}, + {"tey", addr_absolute_x}, + {"STA", addr_absolute_x}, + {"tex", addr_absolute_y}, + {"tea", addr_absolute_y}, + {"LDY", addr_immediate}, + {"LDA", addr_indirect_x}, + {"LDX", addr_immediate}, + {"lax", addr_indirect_x}, + {"LDY", addr_zeropage}, + {"LDA", addr_zeropage}, + {"LDX", addr_zeropage}, + {"lax", addr_zeropage}, + {"TAY", addr_implied}, + {"LDA", addr_immediate}, + {"TAX", addr_implied}, + {"ama", addr_immediate}, + {"LDY", addr_absolute}, + {"LDA", addr_absolute}, + {"LDX", addr_absolute}, + {"lax", addr_absolute}, + {"BCS", addr_relative}, + {"LDA", addr_indirect_y}, + {"hang", addr_implied}, + {"lax", addr_indirect_y}, + {"LDY", addr_zeropage_x}, + {"LDA", addr_zeropage_x}, + {"LDX", addr_zeropage_y}, + {"laz", addr_zeropage_y}, + {"CLV", addr_implied}, + {"LDA", addr_absolute_y}, + {"TSX", addr_implied}, + {"las", addr_absolute_y}, + {"LDY", addr_absolute_x}, + {"LDA", addr_absolute_x}, + {"LDX", addr_absolute_y}, + {"lax", addr_absolute_y}, + {"CPY", addr_immediate}, + {"CMP", addr_indirect_x}, + {"nop", addr_immediate}, + {"dcp", addr_indirect_x}, + {"CPY", addr_zeropage}, + {"CMP", addr_zeropage}, + {"DEC", addr_zeropage}, + {"dcp", addr_zeropage}, + {"INY", addr_implied}, + {"CMP", addr_immediate}, + {"DEX", addr_implied}, + {"axm", addr_immediate}, + {"CPY", addr_absolute}, + {"CMP", addr_absolute}, + {"DEC", addr_absolute}, + {"dcp", addr_absolute}, + {"BNE", addr_relative}, + {"CMP", addr_indirect_y}, + {"hang", addr_implied}, + {"dcp", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"CMP", addr_zeropage_x}, + {"DEC", addr_zeropage_x}, + {"dcp", addr_zeropage_x}, + {"CLD", addr_implied}, + {"CMP", addr_absolute_y}, + {"nop", addr_implied}, + {"dcp", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"CMP", addr_absolute_x}, + {"DEC", addr_absolute_x}, + {"dcp", addr_absolute_x}, + {"CPX", addr_immediate}, + {"SBC", addr_indirect_x}, + {"nop", addr_immediate}, + {"isb", addr_indirect_x}, + {"CPX", addr_zeropage}, + {"SBC", addr_zeropage}, + {"INC", addr_zeropage}, + {"isb", addr_zeropage}, + {"INX", addr_implied}, + {"SBC", addr_immediate}, + {"NOP", addr_implied}, + {"zbc", addr_immediate}, + {"CPX", addr_absolute}, + {"SBC", addr_absolute}, + {"INC", addr_absolute}, + {"isb", addr_absolute}, + {"BEQ", addr_relative}, + {"SBC", addr_indirect_y}, + {"hang", addr_implied}, + {"isb", addr_indirect_y}, + {"nop", addr_zeropage_x}, + {"SBC", addr_zeropage_x}, + {"INC", addr_zeropage_x}, + {"isb", addr_zeropage_x}, + {"SED", addr_implied}, + {"SBC", addr_absolute_y}, + {"nop", addr_implied}, + {"isb", addr_absolute_y}, + {"nop", addr_absolute_x}, + {"SBC", addr_absolute_x}, + {"INC", addr_absolute_x}, + {"isb", addr_absolute_x}, +}; diff --git a/src/prefs.c b/src/prefs.c new file mode 100644 index 00000000..647c6162 --- /dev/null +++ b/src/prefs.c @@ -0,0 +1,412 @@ +/* + * Apple // emulator for Linux: Preferences file maintenance + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include "misc.h" +#include "prefs.h" +#include "keys.h" +#include "interface.h" +#include "cpu.h" + +#define PRM_NONE 0 +#define PRM_SPEED 1 +#define PRM_MODE 2 +#define PRM_DISK_PATH 3 +#define PRM_HIRES_COLOR 4 +#define PRM_SOUND 5 +#define PRM_JOY_INPUT 6 +#define PRM_JOY_RANGE 7 +#define PRM_JOY_OX 8 +#define PRM_JOY_OY 9 +#define PRM_JOY_PC_CALIBRATE 10 +#define PRM_JOY_KYBD_SENSITIVITY 11 +#define PRM_ROM_PATH 12 + + +char system_path[SYSSIZE]; +char disk_path[DISKSIZE]; + +int apple_mode; +int sound_mode; +int color_mode; +short joy_mode; +short joy_step; +short joy_center_x; +short joy_center_y; +short joy_range; +short half_joy_range; + +#ifdef PC_JOYSTICK +int js_center_x; +int js_center_y; +long js_timelimit; +int js_max_x; +int js_max_y; +int js_min_x; +int js_min_y; +#endif /* PC_JOYSTICK */ + +static char *config_filename; + +struct match_table + { + const char *tag; + int value; + }; + +static const struct match_table prefs_table[] = +{ + {"speed", PRM_SPEED}, + {"mode", PRM_MODE}, + {"path", PRM_DISK_PATH}, + {"disk path", PRM_DISK_PATH}, + {"disk_path", PRM_DISK_PATH}, + {"path", PRM_DISK_PATH}, + {"color", PRM_HIRES_COLOR}, + {"sound", PRM_SOUND}, + {"joystick", PRM_JOY_INPUT}, + {"joy range", PRM_JOY_RANGE}, + {"joystick range", PRM_JOY_RANGE}, + {"joy_range", PRM_JOY_RANGE}, + {"origin_x", PRM_JOY_OX}, + {"origin_y", PRM_JOY_OY}, + {"pc joystick parms", PRM_JOY_PC_CALIBRATE}, + {"pc_joystick_parms", PRM_JOY_PC_CALIBRATE}, + {"sensitivity", PRM_JOY_KYBD_SENSITIVITY}, + {"system path", PRM_ROM_PATH}, + {"system_path", PRM_ROM_PATH}, + {0, PRM_NONE} +}; + +static const struct match_table modes_table[] = +{ + {"][+", II_MODE}, + {"][+ undocumented", IIU_MODE}, +#ifdef APPLE_IIE + {"//e", IIE_MODE}, + {0, IIE_MODE} +#else /* !APPLE_IIE */ + {0, IIU_MODE} +#endif /* !APPLE_IIE */ +}; + +static const struct match_table color_table[] = +{ + {"black/white", NO_COLOR}, + {"lazy color", LAZY_COLOR}, + {"color", COLOR}, + {"lazy interpolated", LAZY_INTERP}, + {"interpolated", INTERP}, + {"off", 0}, + {"on", COLOR}, + {0, COLOR} +}; + +static const struct match_table sound_table[] = +{ + {"off", 0}, + {"pc_speaker", 1}, + {"on", 1}, + {0, 1}, +}; + +static const struct match_table joy_input_table[] = +{ + {"off", JOY_OFF}, + {"keyboard", JOY_KYBD}, + {"linear", JOY_KYBD}, +#ifdef PC_JOYSTICK + {"pc joystick", JOY_PCJOY}, + {"pc_joystick", JOY_PCJOY}, +#endif /* PC_JOYSTICK */ +#if 0 + {"digital", JOY_DIGITAL}, +#endif /* 0 */ + {0, JOY_KYBD} +}; + +/* Find the number assigned to KEYWORD in a match table PARADIGM. If no match, + * then the value associated with the terminating entry is used as a + * default. */ +static int +match (const struct match_table *paradigm, const char *keyword) +{ + while (paradigm->tag && strcasecmp (paradigm->tag, keyword)) + paradigm++; + return paradigm->value; +} + +/* Reverse match -- find a keyword associated with number KEY in + * PARADIGM. The first match is used -- synonym keywords appearing later + * in the table are not chosen. + * + * A null is returned for no match. + */ +static const char *reverse_match (const struct match_table *paradigm, int key) +{ + while (paradigm->tag && key != paradigm->value) + paradigm++; + return paradigm->tag; +} + +/* Eat leading and trailing whitespace of string X. The old string is + * overwritten and a new pointer is returned. + */ +static char * +clean_string (char *x) +{ + size_t y; + + /* Leading white space */ + while (isspace (*x)) x++; + + /* Trailing white space */ + y = strlen (x); + while (y && x[y--] == ' '); + x[y] = 0; + + return x; +} + +/* Load the configuration. Must be called *once* at start. */ +void +load_settings (void) +{ + /* set system defaults before user defaults. */ + strcpy (disk_path, "./disks"); + strcpy (system_path, "./rom"); + + { + const char *homedir; + + homedir = getenv ("HOME"); + config_filename = malloc (strlen (homedir) + 9); + strcpy (config_filename, homedir); + strcat (config_filename, "/.apple2"); + + /* config_filename is left allocated for convinence in + * save_settings */ + } + + { + FILE *config_file; + char *buffer = 0; + size_t size = 0; + + config_file = fopen (config_filename, "r"); + if (config_file == NULL) + { + printf ( + "Warning. Cannot open the .apple2 system defaults file.\n" + "Make sure it's readable in your home directory."); + printf ("Press RETURN to continue..."); + getchar (); + return; + } + + while (getline (&buffer, &size, config_file) != -1) + { + char *parameter; + char *argument; + + /* Split line between parameter and argument */ + + parameter = buffer; + argument = strchr (buffer, '='); + argument[0] = 0; + argument++; + + parameter = clean_string (parameter); + argument = clean_string (argument); + + switch (match (prefs_table, parameter)) + { + case PRM_NONE: + fprintf (stderr, "Unrecognized config parameter `%s'", parameter); + break; + + case PRM_SPEED: + { + int x; + + x = strtol (argument, 0, 0); + + if (x < 0) + x = 0; + + cpu65_delay = MAX_APPLE_DELAY - x + 1; + if (cpu65_delay < 1) + cpu65_delay = 1; + } + break; + + case PRM_MODE: + apple_mode = match (modes_table, argument); + break; + + case PRM_DISK_PATH: + strncpy (disk_path, argument, DISKSIZE); + break; + + case PRM_HIRES_COLOR: + color_mode = match (color_table, argument); + break; + + case PRM_SOUND: + sound_mode = match (sound_table, argument); + break; + + case PRM_JOY_INPUT: + joy_mode = match (joy_input_table, argument); + break; + + case PRM_JOY_RANGE: + joy_range = strtol (argument, 0, 0); + if (joy_range < 10) + joy_range = 10; + else if (joy_range > 256) + joy_range = 256; + half_joy_range = joy_range / 2; + + if (joy_center_x > joy_range) + joy_center_x = half_joy_range; + if (joy_center_y > joy_range) + joy_center_y = half_joy_range; + break; + + case PRM_JOY_OX: + joy_center_x = strtol (argument, 0, 0); + if (joy_center_x < 0) + joy_center_x = 0; + else if (joy_center_x > 255) + joy_center_x = 255; + + if (joy_center_x > joy_range) + joy_center_x = half_joy_range; + break; + + case PRM_JOY_OY: + joy_center_y = strtol (argument, 0, 0); + if (joy_center_y < 0) + joy_center_y = 0; + else if (joy_center_y > 255) + joy_center_y = 255; + + if (joy_center_y > joy_range) + joy_center_y = half_joy_range; + break; + + case PRM_JOY_PC_CALIBRATE: +#ifdef PC_JOYSTICK + /* pc joystick parms generated by the calibration routine + (shouldn't need to hand tweak these) = origin_x origin_y max_x + min_x max_y min_y js_timelimit */ + js_center_x = strtol (argument, &argument, 10); + js_center_y = strtol (argument, &argument, 10); + js_max_x = strtol (argument, &argument, 10); + if (js_max_x < 0) + js_max_x = 0; + js_min_x = strtol (argument, &argument, 10); + if (js_min_x < 0) + js_min_x = 0; + + js_max_y = strtol (argument, &argument, 10); + if (js_max_y < 0) + js_max_y = 0; + js_min_y = strtol (argument, &argument, 10); + if (js_min_y < 0) + js_min_y = 0; + + js_timelimit = strtol (argument, &argument, 10); + if (js_timelimit < 2) + js_timelimit = 2; + + c_open_joystick (); + c_calculate_joystick_parms (); /* calculate the associated parms */ +#endif + + case PRM_JOY_KYBD_SENSITIVITY: + joy_step = strtol (argument, 0, 0); + if (joy_step < 1) + joy_step = 1; + else if (joy_step > 100) + joy_step = 100; + break; + + case PRM_ROM_PATH: + strncpy (system_path, argument, SYSSIZE); + break; + } + } + fclose (config_file); + } +} + + +/* Save the configuration */ +void +save_settings (void) +{ + FILE *config_file; + + config_file = fopen (config_filename, "w"); + if (config_file == NULL) + { + printf ( + "Cannot open the .apple2 system defaults file for writing.\n" + "Make sure it has rw permission in your home directory."); + return; + } + + fprintf (config_file, + "speed = %d\n" + "mode = %s\n" + "disk path = %s\n" + "color = %s\n" + "sound = %s\n" + "joystick = %s\n" + "joystick range = %d\n" + "origin_x = %d\n" + "origin_y = %d\n" + "sensitivity = %d%%\n" + "system path = %s\n", + MAX_APPLE_DELAY + 1 - cpu65_delay, + reverse_match (modes_table, apple_mode), + disk_path, + reverse_match (color_table, color_mode), + reverse_match (sound_table, sound_mode), + reverse_match (joy_input_table, joy_mode), + joy_range, + joy_center_x, + joy_center_y, + joy_step, + system_path); + +#ifdef PC_JOYSTICK + fprintf (config_file, + "pc joystick parms = %d %d %d %d %d %d %ld\n", + js_center_x, js_center_y, js_max_x, js_min_x, + js_max_y, js_min_y, js_timelimit); +#endif + + fclose (config_file); +} diff --git a/src/prefs.h b/src/prefs.h new file mode 100644 index 00000000..d97da79e --- /dev/null +++ b/src/prefs.h @@ -0,0 +1,74 @@ +/* + * Apple // emulator for Linux: Configuration defines + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef PREFS_H +#define PREFS_H + +#ifndef __ASSEMBLER__ + +#define SYSSIZE 4096 +extern char system_path[SYSSIZE]; +#define DISKSIZE 4096 +extern char disk_path[DISKSIZE]; + +extern int apple_mode; /* undocumented instructions or //e mode */ +extern int sound_mode; /* PC speaker or OFF */ +extern int color_mode; + +/* generic joystick settings */ +extern short joy_mode; +extern short joy_step; +extern short joy_center_x; +extern short joy_center_y; +extern short joy_range; +extern short half_joy_range; + +#ifdef PC_JOYSTICK +/* real joystick settings */ +extern int js_center_x; +extern int js_center_y; +extern long js_timelimit; +extern int js_max_x; +extern int js_max_y; +extern int js_min_x; +extern int js_min_y; +#endif /* PC_JOYSTICK */ + +/* functions in prefs.c */ +extern void load_settings(void); +extern void save_settings(void); + +#endif /* !__ASSEMBLER__ */ + +/* values for apple_mode */ +#define IIE_MODE 2 +#define IIU_MODE 1 +#define II_MODE 0 + +/* values for color_mode */ +#define NO_COLOR 0 +#define LAZY_COLOR 1 +#define COLOR 2 +#define LAZY_INTERP 3 +#define INTERP 4 + +/* values for joy_mode */ +#define JOY_OFF 0 +#define JOY_KYBD 1 +#define JOY_DIGITAL 2 +#define JOY_PCJOY 3 + +#endif /* PREFS_H */ diff --git a/src/svideo.c b/src/svideo.c new file mode 100644 index 00000000..1b852150 --- /dev/null +++ b/src/svideo.c @@ -0,0 +1,215 @@ +/* + * Apple // emulator for Linux: svgalib graphics support + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "video.h" +#include "misc.h" +#include "keys.h" + +/* I need at least 560x192 for 80col. it seems that direct linear + * framebuffer access to anything in the realm of 640x480x256 not + * standard with vga/svga? + * Memory sizes are hardcode here. ugly ugly ugly. + */ + +static unsigned char *svga_GM; /* SVGA base address of graphic area */ +static unsigned char vga_mem_page_0[64000]; /* page0 framebuffer */ +static unsigned char vga_mem_page_1[64000]; /* page1 framebuffer */ + + +/* ------------------------------------------------------------------------- + video_setpage(p): Switch to screen page p + ------------------------------------------------------------------------- */ +void video_setpage(int p) +{ + if (p == video__current_page) return; + + if (p) + { + memcpy(vga_mem_page_0,svga_GM,64000); + memcpy(svga_GM,vga_mem_page_1,64000); + video__current_page = 1; + video__fb1 = vga_mem_page_0; + video__fb2 = svga_GM; + } + else + { + memcpy(vga_mem_page_1,svga_GM,64000); + memcpy(svga_GM,vga_mem_page_0,64000); + video__current_page = 0; + video__fb1 = svga_GM; + video__fb2 = vga_mem_page_1; + } +} + +/* ------------------------------------------------------------------------- + c_initialize_colors(): Initialize color palette + ------------------------------------------------------------------------- */ + +static void c_initialize_colors() +{ + + static unsigned int col2[ 3 ] = { 27, 40, 62 }; + + int i, j; + + /* align the palette for hires graphics */ + for (i = 0; i < 8; i++) + for (j = 0; j < 3; j++) + vga_setpalette( j+i*3+32, (i & 1) ? col2[ j ] : 0, + (i & 2) ? col2[ j ] : 0, + (i & 4) ? col2[ j ] : 0 ); + + vga_setpalette( COLOR_FLASHING_BLACK, 0, 0, 0 ); + vga_setpalette( COLOR_FLASHING_WHITE, 63, 63, 63 ); + + /* dhires colors are bass-ackwards because it's easier for me to + deal with the endianness. */ + vga_setpalette( 0x0, 0, 0, 0 ); /* (0) Black */ + vga_setpalette( 0x1, 0, 0, 32 ); /* (2) Dark Blue */ + vga_setpalette( 0x2, 0, 36, 0 ); /* (4) Dark Green */ + vga_setpalette( 0x3, 28, 6, 63 ); /* (6) Medium Blue */ + vga_setpalette( 0x4, 37, 21, 10 ); /* (8) Brown */ + vga_setpalette( 0x5, 37, 42, 42 ); /* (a) Light Grey */ + vga_setpalette( 0x6, 0, 63, 0 ); /* (c) Green */ + vga_setpalette( 0x7, 32, 63, 32 ); /* (e) Aqua */ + vga_setpalette( 0x8, 48, 0, 12 ); /* (1) Magenta */ + vga_setpalette( 0x9, 41, 13, 42 ); /* (3) Purple */ + vga_setpalette( 0xa, 26, 26, 26 ); /* (5) Light Grey */ + vga_setpalette( 0xb, 3, 47, 58 ); /* (7) Light Blue */ + vga_setpalette( 0xc, 63, 6, 11 ); /* (9) Orange */ + vga_setpalette( 0xd, 63, 39, 37 ); /* (b) Pink */ + vga_setpalette( 0xe, 63, 63, 0 ); /* (d) Yellow */ + vga_setpalette( 0xf, 63, 63, 63 ); /* (f) White */ + + /* lores colors (<<4) */ + vga_setpalette(0x10, 48, 0, 12 ); /* Magenta */ + vga_setpalette(0x20, 0, 0, 32 ); /* Dark Blue */ + vga_setpalette(0x30, 41, 13, 42 ); /* Purple */ + vga_setpalette(0x40, 0, 36, 0 ); /* Dark Green */ + vga_setpalette(0x50, 26, 26, 26 ); /* Dark Gray */ + vga_setpalette(0x60, 28, 6, 63 ); /* Medium Blue */ + vga_setpalette(0x70, 3, 47, 58 ); /* Light Blue */ + vga_setpalette(0x80, 37, 21, 10 ); /* Brown */ + vga_setpalette(0x90, 63, 6, 11 ); /* Orange */ + vga_setpalette(0xa0, 37, 42, 42 ); /* Light Grey */ + vga_setpalette(0xb0, 63, 39, 37 ); /* Pink */ + vga_setpalette(0xc0, 0, 63, 0 ); /* Green */ + vga_setpalette(0xd0, 63, 63, 0 ); /* Yellow */ + vga_setpalette(0xe0, 32, 63, 32 ); /* Aqua */ + vga_setpalette(0xf0, 63, 63, 63 ); /* White */ +} + +/* ------------------------------------------------------------------------- + c_initialize_keyboard() + ------------------------------------------------------------------------- */ + +static void c_initialize_keyboard() +{ + if (keyboard_init()) { + printf("Error: Could not switch to RAW keyboard mode.\n"); + exit(-1); + } + + keyboard_translatekeys(DONT_CATCH_CTRLC); + keyboard_seteventhandler( c_read_raw_key ); +} + +static void c_flash_cursor(int on) { + if (!on) { + vga_setpalette( COLOR_FLASHING_BLACK, 0, 0, 0 ); + vga_setpalette( COLOR_FLASHING_WHITE, 63, 63, 63 ); + } else { + vga_setpalette( COLOR_FLASHING_BLACK, 63, 63, 63 ); + vga_setpalette( COLOR_FLASHING_WHITE, 0, 0, 0 ); + } +} + +/* ------------------------------------------------------------------------- + video_init() + ------------------------------------------------------------------------- */ +void video_init(void) { + /* I'm forcing VGA mode since it seems to be supported by + * the lowest common denominator cards. + */ + printf("Using standard VGA 320x200 mode.\n"); + printf("Press RETURN to continue..."); + getchar(); + + vga_setchipset( VGA ); + if (vga_init()) { + printf("Cannot initialize svgalib!\n"); + exit(1); + } + + vga_setmode( G320x200x256 ); + +/* vga_claimvideomemory( 131072 );*/ + c_initialize_keyboard(); + svga_GM = video__fb1 = vga_getgraphmem(); + video__fb2 = vga_mem_page_1; + + memset(video__fb1,0,64000); /* start as black */ + memset(video__fb2,0,64000); + + c_initialize_colors(); + + + + + + +} + +void video_shutdown(void) { + vga_setmode(TEXT); + keyboard_close(); +} + +void video_sync(int block) +{ + static int flash_count; + + if (block) + { + /* keyboard_waitforupdate(); --- seems to cause bad crashes... */ + usleep(TIMER_DELAY); + keyboard_update(); + } + else + keyboard_update(); + + switch (++flash_count) + { + case 6: + c_flash_cursor(1); + break; + case 12: + c_flash_cursor(0); + flash_count = 0; + break; + default: + break; + } +} diff --git a/src/video.h b/src/video.h new file mode 100644 index 00000000..364ce397 --- /dev/null +++ b/src/video.h @@ -0,0 +1,232 @@ +/* + * Apple // emulator for Linux: Video definitions + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#ifndef A2_VIDEO_H +#define A2_VIDEO_H + +#ifndef __ASSEMBLER__ + +/* Prepare the video system, converting console to graphics mode, or + * opening X window, or whatever. This is called only once when the + * emulator is run + */ +void video_init(void); + +/* Undo anything done by video_init. This is called before exiting the + * emulator. + */ +void video_shutdown(void); + +/* Setup the display. This may be called multiple times in a run, and is + * used when graphics parameters (II+ vs //e, hires color representation) may + * have changed. + * + * In future, all relevant information will be communicated through + * FLAGS. For now, however, it is ignored and global variables are used + * instead. + * + * This function is responsible for inserting any needed video-specific hooks + * into the 6502 memory indirection table. It should *not* hook the + * soft-switches. + * + */ +void video_set(int flags); + +/* Set the font used by the display. QTY characters are loaded starting + * with FIRST, from DATA. DATA contains 8 bytes for each character, each + * byte representing a row (top-to-bottom). The row byte contains 7 + * pixels in little-endian format. + * + * MODE selects the colors to use + * + * 0 - Normal text + * 1 - MouseText (usually treat as Normal) + * 2 - Inverse + * 3 - Flash + * + * The extra MouseText mode is in case we want to emulate certain RGB + * adaptors which color normal text and MouseText differently. I had one + * once for a //c. + */ +void video_loadfont(int first, + int qty, + const unsigned char *data, + int mode); + +/* Redraw the display. This is called after exiting an interface display, + * when changes have been made to the Apple's emulated framebuffer that + * bypass the driver's hooks, or when the video mode has changed. + */ +void video_redraw(void); + +/* Change the displayed video page to PAGE + * 0 - Page 1: $400-$7ff/$2000-$3fff + * 1 - Page 2: $800-$bff/$4000-$5fff + */ +void video_setpage(int page); + +/* Like loadfont, but writes to a seperate 256 character table used by + * video_plotchar and not the apple text-mode display. + */ +void video_loadfont_int(int first, int qty, const unsigned char *data); + +/* Plot a character to the text mode screen, *not* writing to apple + * memory. This is used by the interface screens. + * + * ROW, COL, and CODE are self-expanatory. COLOR gives the color scheme + * to use: + * + * 0 - Green text on Black background + * 1 - Green text on Blue background + * 2 - Red text on Black background + */ +void video_plotchar(int row, int col, int color, unsigned char code); + +/* Called at about 30Hz (this may change in future), and when waiting in + * the interface screens. + * + * Should flush any video data to the real screen (if any kind of caching + * is in use), check for keyboard input (presently reported via + * c_read_raw_key), and handle flashing text characters. + */ +void video_sync(int block); + +#endif /* !__ASSEMBLER__ */ + +/**** Private stuff follows *****/ + +#ifdef _640x400 +/* 640x400 mode really isn't what it advertises. It's really 560x384 with 4 + * extra bytes on each side for color interpolation hack. This is yet another + * area where I've traded the optimization gain (especially on older slower + * machines) for a standard resolution. + */ +#define SCANWIDTH 568 +#define SCANHEIGHT 384 +#define SCANSTEP SCANWIDTH-12 +#else /* !_640x400 */ +#define SCANWIDTH 320 +#define SCANHEIGHT 200 +#define SCANSTEP SCANWIDTH-6 +#endif /* !_640x400 */ + +#define COLOR_BLACK 0 + +#define COLOR_DARK_RED 35 +#define COLOR_MEDIUM_RED 36 +#define COLOR_LIGHT_RED 37 /* hgr used */ + +#define COLOR_DARK_GREEN 38 +#define COLOR_MEDIUM_GREEN 39 +#define COLOR_LIGHT_GREEN 40 /* hgr used */ + +#define COLOR_DARK_YELLOW 41 +#define COLOR_MEDIUM_YELLOW 42 +#define COLOR_LIGHT_YELLOW 43 + +#define COLOR_DARK_BLUE 44 +#define COLOR_MEDIUM_BLUE 45 +#define COLOR_LIGHT_BLUE 46 /* hgr used */ + +#define COLOR_DARK_PURPLE 47 +#define COLOR_MEDIUM_PURPLE 48 +#define COLOR_LIGHT_PURPLE 49 /* hgr used */ + +#define COLOR_DARK_CYAN 50 +#define COLOR_MEDIUM_CYAN 51 +#define COLOR_LIGHT_CYAN 52 + +#define COLOR_DARK_WHITE 53 +#define COLOR_MEDIUM_WHITE 54 +#define COLOR_LIGHT_WHITE 55 + +#define COLOR_FLASHING_BLACK 56 +#define COLOR_FLASHING_WHITE 57 +#define COLOR_FLASHING_UNGREEN 58 +#define COLOR_FLASHING_GREEN 59 + + +#ifndef __ASSEMBLER__ +/* ---------------------------------- + generic graphics globals + ---------------------------------- */ + +/* Pointers to framebuffer (can be VGA memory or host buffer) + */ + +extern unsigned char *video__fb1,*video__fb2; + +#ifdef _640x400 +extern unsigned char video__wider_hires_even[0x1000]; +extern unsigned char video__wider_hires_odd[0x1000]; +#endif /* _640x400 */ + +extern unsigned char video__hires_even[0x800]; +extern unsigned char video__hires_odd[0x800]; + +extern unsigned char video__dhires1[256]; +extern unsigned char video__dhires2[256]; + +extern int video__current_page; /* Current visual page */ + +extern int video__strictcolors; + +#ifdef _640x400 +extern unsigned char video__wider_int_font[3][0x8000]; +#else /* _640x400 */ +extern unsigned char video__int_font[3][0x4000]; +#endif /* _640x400 */ + +/* --- Precalculated hi-res page offsets given addr --- */ +extern unsigned int video__screen_addresses[8192]; +extern unsigned char video__columns[8192]; + +extern unsigned char video__odd_colors[2]; +extern unsigned char video__even_colors[2]; + +/* Hooks */ + +void video__write_text0(), + video__write_text0_mixed(), + video__write_text1(), + video__write_text1_mixed(), + video__write_even0(), + video__write_odd0(), + video__write_even0_mixed(), + video__write_odd0_mixed(), + video__write_even1(), + video__write_odd1(), + video__write_even1_mixed(), + video__write_odd1_mixed(); + +#ifdef APPLE_IIE +void video__write_2e_text0(), + video__write_2e_text0_mixed(), + video__write_2e_text1(), + video__write_2e_text1_mixed(), + video__write_2e_odd0(), + video__write_2e_even0(), + video__write_2e_odd0_mixed(), + video__write_2e_even0_mixed(), + video__write_2e_odd1(), + video__write_2e_even1(), + video__write_2e_odd1_mixed(), + video__write_2e_even1_mixed(); +#endif /* APPLE_IIE */ + +#endif /* !__ASSEMBLER__ */ + +#endif /* !A2_VIDEO_H */ diff --git a/src/vidsup.c b/src/vidsup.c new file mode 100644 index 00000000..b29ec278 --- /dev/null +++ b/src/vidsup.c @@ -0,0 +1,679 @@ +/* + * Apple // emulator for Linux: Video support + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include "video.h" +#include "cpu.h" +#include "misc.h" +#include "prefs.h" + +#ifdef _640x400 +unsigned char video__wider_font[0x8000]; +#endif /* _640x400 */ + +unsigned char video__font[0x4000]; + +/* --- Precalculated hi-res page offsets given addr --- */ +unsigned int video__screen_addresses[8192]; +unsigned char video__columns[8192]; + +unsigned char *video__fb1,*video__fb2; + +#ifdef _640x400 +unsigned char video__wider_hires_even[0x1000]; +unsigned char video__wider_hires_odd[0x1000]; +#endif +unsigned char video__hires_even[0x800]; +unsigned char video__hires_odd[0x800]; + +unsigned char video__dhires1[256]; +unsigned char video__dhires2[256]; + +/* Interface font: + * (probably could be made static) + * + * Unlike the normal font, only one version is stored, since the interface + * is always displayed in forty columns. + */ +#ifdef _640x400 +unsigned char video__wider_int_font[3][0x8000]; +#else /* _640x400 */ +unsigned char video__int_font[3][0x4000]; +#endif /* _640x400 */ + +int video__current_page; /* Current visual page */ + +int video__strictcolors; + +void video_loadfont(int first, + int quantity, + const unsigned char *data, + int mode) +{ + int i,j; + unsigned char x,y,fg,bg; + + switch(mode) + { + case 2: + fg = COLOR_BLACK; bg = COLOR_LIGHT_WHITE; break; + case 3: + fg = COLOR_FLASHING_WHITE; bg = COLOR_FLASHING_BLACK; break; + default: + fg = COLOR_LIGHT_WHITE; bg = COLOR_BLACK; break; + } + + i = quantity * 8; + + while (i--) + { + j = 8; + x = data[i]; + while (j--) + { + y = (x & 128) ? fg : bg; + +#ifdef _640x400 + video__wider_font[(first << 7) + (i << 4) + (j << 1)] = + video__wider_font[(first << 7) + (i << 4) + (j << 1) + 1] = +#endif /* _640x400 */ + video__font[(first << 6) + (i << 3) + j] = y; + x <<= 1; + } + } +} + +unsigned char video__odd_colors[2] = {COLOR_LIGHT_PURPLE, COLOR_LIGHT_BLUE}; +unsigned char video__even_colors[2] = {COLOR_LIGHT_GREEN, COLOR_LIGHT_RED}; + +/* 40col/80col/lores/hires/dhires line offsets */ +unsigned short video__line_offset[24] = + { 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, + 0x028, 0x0A8, 0x128, 0x1A8, 0x228, 0x2A8, 0x328, 0x3A8, + 0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 }; + +unsigned char video__dhires1[256] = { + 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, + 0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0x9,0x9,0xb,0xb,0xd,0xd,0xf,0xf, + 0x0,0x1,0x2,0x3,0x6,0x5,0x6,0x7,0xa,0x9,0xa,0xb,0xe,0xd,0xe,0xf, + 0x0,0x1,0x3,0x3,0x7,0x5,0x7,0x7,0xb,0x9,0xb,0xb,0xf,0xd,0xf,0xf, + 0x0,0x1,0x2,0x3,0x4,0x4,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf, + 0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0xd,0x9,0xb,0xb,0xd,0xd,0xf,0xf, + 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0xe,0x9,0xa,0xb,0xe,0xd,0xe,0xf, + 0x0,0x1,0x7,0x3,0x7,0x5,0x7,0x7,0xf,0x9,0xb,0xb,0xf,0xd,0xf,0xf, +}; + +unsigned char video__dhires2[256] = { + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x8,0x0,0xb,0x8,0xd,0x0,0x0, + 0x1,0x1,0x1,0x1,0x0,0x5,0x1,0x1,0x0,0x9,0xb,0xb,0x0,0xd,0xf,0xf, + 0x0,0x1,0x2,0x2,0x2,0x5,0x2,0x2,0x0,0xa,0xa,0xa,0xe,0xd,0x2,0x2, + 0x3,0x3,0x3,0x3,0x7,0x5,0x7,0x7,0x0,0xb,0xb,0xb,0xf,0xd,0xf,0xf, + 0x0,0x0,0x4,0x0,0x4,0x4,0x4,0x4,0xc,0x8,0x4,0x8,0xc,0xd,0x4,0x4, + 0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0xd,0x4,0x4,0x4,0xd,0xd,0x4,0x4, + 0x6,0x6,0x6,0x2,0xe,0x6,0x6,0x6,0xe,0xe,0xa,0xa,0xe,0x6,0xe,0x6, + 0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0xf,0xf,0xb,0xb,0xf,0xf,0xf,0xf, +}; + +#ifdef APPLE_IIE + +/* ------------------------------------------------------------------------- + c_initialize_dhires_values() + ------------------------------------------------------------------------- */ +static void c_initialize_dhires_values(void) { + int i; +/* int value, v; */ +/* unsigned char locolor, hicolor; */ + + /* precalculate the colors for all the 256*8 bit combinations. */ +/* for (value = 0x00, v = 0; value <= 0xFF; value++) { */ +/* locolor = (value & 0x0F) | 0x10; */ +/* hicolor = (value << 4) | 0x10; */ + +/* dhires_colors[v++] = locolor; */ +/* dhires_colors[v++] = locolor; */ +/* dhires_colors[v++] = locolor; */ +/* dhires_colors[v++] = locolor; */ + +/* dhires_colors[v++] = hicolor; */ +/* dhires_colors[v++] = hicolor; */ +/* dhires_colors[v++] = hicolor; */ +/* dhires_colors[v++] = hicolor; */ +/* } */ + + for (i = 0; i < 0x80; i++) { + video__dhires1[i+0x80] = video__dhires1[i]; + video__dhires2[i+0x80] = video__dhires2[i]; + } +} +#endif + +/* ------------------------------------------------------------------------- + c_initialize_hires_values() + ------------------------------------------------------------------------- */ + +static void c_initialize_hires_values(void) +{ + int value, b, v, e, /*color_toggle,*/ last_not_black; + + /* precalculate the colors for all the 256*8 bit combinations. */ + for (value = 0x00; value <= 0xFF; value++) { + for (e = value * 8, last_not_black = 0, v = value, b = 0; + b < 7; b++, v >>= 1, e++) + { + if (v & 1) + { + video__hires_even[ e ] = last_not_black ? + COLOR_LIGHT_WHITE : + ((b & 1) ? + ((value & 0x80) ? + COLOR_LIGHT_RED : + COLOR_LIGHT_GREEN) : + ((value & 0x80) ? + COLOR_LIGHT_BLUE : + COLOR_LIGHT_PURPLE)); + + video__hires_odd[ e ] = last_not_black ? + COLOR_LIGHT_WHITE : + ((b & 1) ? + ((value & 0x80) ? + COLOR_LIGHT_BLUE : + COLOR_LIGHT_PURPLE) : + ((value & 0x80) ? + COLOR_LIGHT_RED : + COLOR_LIGHT_GREEN)); + + if (last_not_black && b > 0) + video__hires_even[ e - 1 ] = COLOR_LIGHT_WHITE, + video__hires_odd[ e - 1 ] = COLOR_LIGHT_WHITE; + + last_not_black = 1; + } + else + video__hires_even[ e ] = COLOR_BLACK, + video__hires_odd[ e ] = COLOR_BLACK, + last_not_black = 0; + } + } + if (color_mode == 0) { /* Black and White */ + for (value = 0x00; value <= 0xFF; value++) { + for (b = 0, e = value * 8; b < 7; b++, e++) { + if (video__hires_even[ e ] != COLOR_BLACK) + video__hires_even[ e ] = COLOR_LIGHT_WHITE; + if (video__hires_odd[ e ] != COLOR_BLACK) + video__hires_odd[ e ] = COLOR_LIGHT_WHITE; + } + } + } + else if (color_mode == LAZY_INTERP) /* Lazy Interpolated color */ + { + for (value = 0x00; value <= 0xFF; value++) + { + for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2) + { + if (video__hires_even[ e ] == COLOR_BLACK && + video__hires_even[ e - 1 ] != COLOR_BLACK && + video__hires_even[ e + 1 ] != COLOR_BLACK) + video__hires_even[ e ] = + video__hires_even[ e - 1 ]; + + if (video__hires_odd[ e ] == COLOR_BLACK && + video__hires_odd[ e - 1 ] != COLOR_BLACK && + video__hires_odd[ e + 1 ] != COLOR_BLACK) + video__hires_odd[ e ] = + video__hires_odd[ e - 1 ]; + } + + for (b = 0, e = value * 8; b <= 6; b += 2, e += 2) { + if (video__hires_odd[ e ] == COLOR_BLACK) { + if (b > 0 && b < 6) { + if (video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_LIGHT_WHITE && + video__hires_even[e-1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e-1]; + } else if (b == 0) { + if (video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e+1]; + } else { + if (video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_LIGHT_WHITE) + video__hires_even[ e ] = + video__hires_even[ e - 1 ]; + } + } + + if (video__hires_odd[ e ] == COLOR_BLACK) { + if (b > 0 && b < 6) { + if (video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + } + else if (b == 0) { + if (video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e+1]; + } + else if + (video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + } + } + } + } + else if (color_mode == INTERP) { /* Color and strict interpolation */ + for (value = 0x00; value <= 0xFF; value++) { + for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2) { + if (video__hires_even[e] == COLOR_BLACK) { + if (video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_LIGHT_WHITE && + video__hires_even[e+1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e-1]; + + else if ( + video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_LIGHT_WHITE && + video__hires_even[e+1] == COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e-1]; + + else if ( + video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] == COLOR_LIGHT_WHITE && + video__hires_even[e+1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e+1]; + + else if ( + video__hires_even[e-1] == COLOR_LIGHT_WHITE && + video__hires_even[e+1] == COLOR_LIGHT_WHITE) + video__hires_even[e] = (value & 0x80) + ? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE; + + } + if (video__hires_odd[e] == COLOR_BLACK) { + if (video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + + else if ( + video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE && + video__hires_odd[e+1] == COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + + else if ( + video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] == COLOR_LIGHT_WHITE && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e+1]; + + else if ( + video__hires_odd[e-1] == COLOR_LIGHT_WHITE && + video__hires_odd[e+1] == COLOR_LIGHT_WHITE) + video__hires_odd[e] = (value & 0x80) + ? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN; + } + } + + for (b = 0, e = value * 8; b <= 6; b += 2, e += 2) { + if (video__hires_even[ e ] == COLOR_BLACK) { + if (b > 0 && b < 6) { + if (video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_LIGHT_WHITE && + video__hires_even[e+1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e-1]; + + else if ( + video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] != COLOR_LIGHT_WHITE && + video__hires_even[e+1] == COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e-1]; + + else if ( + video__hires_even[e-1] != COLOR_BLACK && + video__hires_even[e+1] != COLOR_BLACK && + video__hires_even[e-1] == COLOR_LIGHT_WHITE && + video__hires_even[e+1] != COLOR_LIGHT_WHITE) + video__hires_even[e] = + video__hires_even[e+1]; + + else if ( + video__hires_even[e-1] == COLOR_LIGHT_WHITE && + video__hires_even[e+1] == COLOR_LIGHT_WHITE) + video__hires_even[e] = (value & 0x80) + ? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN; + } + } + + if (video__hires_odd[e] == COLOR_BLACK) { + if (b > 0 && b < 6) { + if (video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + + else if ( + video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] != COLOR_LIGHT_WHITE && + video__hires_odd[e+1] == COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e-1]; + + else if ( + video__hires_odd[e-1] != COLOR_BLACK && + video__hires_odd[e+1] != COLOR_BLACK && + video__hires_odd[e-1] == COLOR_LIGHT_WHITE && + video__hires_odd[e+1] != COLOR_LIGHT_WHITE) + video__hires_odd[e] = + video__hires_odd[e+1]; + + else if ( + video__hires_odd[e-1] == COLOR_LIGHT_WHITE && + video__hires_odd[e+1] == COLOR_LIGHT_WHITE) + video__hires_odd[e] = (value & 0x80) + ? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE; + } + } + } + } + } +#ifdef _640x400 + /* *2 for 640x400 */ + for (b=0, e=0; b<4096; b++, e++) { + video__wider_hires_even[b] = video__hires_even[e]; + video__wider_hires_odd[b] = video__hires_odd[e]; + b++; + video__wider_hires_even[b] = video__hires_even[e]; + video__wider_hires_odd[b] = video__hires_odd[e]; + } +#endif +} + + +/* ------------------------------------------------------------------------- + c_initialize_row_col_tables() + ------------------------------------------------------------------------- */ +static void c_initialize_row_col_tables(void) +{ + int x, y, off, i; + + /* hires page offsets. initialize to invalid values. */ + for (i = 0; i < 8192; i++) { + (long)(video__screen_addresses[i]) = -1; + } + + for (y = 0; y < 24; y++) { + for (off = 0; off < 8; off++) { + for (x = 0; x < 40; x++) { +#ifdef _640x400 + video__screen_addresses[video__line_offset[y] + 0x400*off + x ] = + (y*16 + 2*off/* + 8*/) * SCANWIDTH + x*14 + 4; +#else + video__screen_addresses[video__line_offset[y] + 0x400*off + x ] = + (y*8 + off + 4) * 320 + x*7 + 20; +#endif + video__columns[video__line_offset[y] + 0x400*off + x] = + (unsigned char)x; + } + } + } + +} + +static void c_initialize_tables_video(void) { + int x, y, i; + + /* initialize text/lores & hires graphics */ + for (y = 0; y < 24; y++) { /* 24 rows */ + for (x = 0; x < 40; x++) /* 40 cols */ + { +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + /* //e mode: text/lores page 0 */ + cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w = + (y < 20) ? video__write_2e_text0 : + video__write_2e_text0_mixed; + } + else +#endif + { + /* ][+ modes: text/lores page 0 */ + cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w = + (y < 20) ? video__write_text0 : + video__write_text0_mixed; + } + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w = + (y < 20) ? video__write_2e_text1 : + video__write_2e_text1_mixed; + } + else +#endif + { + /* ][+ modes: text/lores page 1 in main memory */ + cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w = + (y < 20) ? video__write_text1 : + video__write_text1_mixed; + } + + for (i = 0; i < 8; i++) + { + /* //e mode: hires/double hires page 0 */ +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[ 0x2000 + video__line_offset[ y ] + + 0x400 * i + x ].w = + (y < 20) ? ((x & 1) ? video__write_2e_odd0 : + video__write_2e_even0) + : ((x & 1) ? video__write_2e_odd0_mixed : + video__write_2e_even0_mixed); + } + + /* ][+ modes: hires page 0 */ + else +#endif + { + cpu65_vmem[ 0x2000 + video__line_offset[ y ] + + 0x400 * i + x ].w = + (y < 20) ? ((x & 1) ? video__write_odd0 : + video__write_even0) + : ((x & 1) ? video__write_odd0_mixed : + video__write_even0_mixed); + } + +#ifdef APPLE_IIE + if (apple_mode == IIE_MODE) { + cpu65_vmem[ 0x4000 + video__line_offset[ y ] + + 0x400 * i + x ].w = + (y < 20) ? ((x & 1) ? video__write_2e_odd1 : + video__write_2e_even1) + : ((x & 1) ? video__write_2e_odd1_mixed : + video__write_2e_even1_mixed); + } + + /* ][+ modes: hires page 1 */ + else +#endif + { + cpu65_vmem[ 0x4000 + video__line_offset[ y ] + + 0x400 * i + x ].w = + (y < 20) ? ((x & 1) ? video__write_odd1 : + video__write_even1) + : ((x & 1) ? video__write_odd1_mixed : + video__write_even1_mixed); + } + } + } + } +} + +void video_set(int flags) +{ + if (color_mode == COLOR) + video__strictcolors = 1; /* strict colors */ + else if (color_mode == INTERP) + video__strictcolors = 2; /* strict interpolation */ + else + video__strictcolors = 0; /* lazy coloration */ + + c_initialize_hires_values(); /* precalculate hires values */ + c_initialize_row_col_tables(); /* precalculate hires offsets */ + c_initialize_tables_video(); /* memory jump tables for video */ + +#ifdef APPLE_IIE + c_initialize_dhires_values(); /* set up dhires colors */ +#endif +} + +void video_loadfont_int(int first, int quantity, const unsigned char *data) +{ + int i,j; + unsigned char x; + int y; + + i = quantity * 8; + + while (i--) + { + j = 8; + x = data[i]; + while (j--) + { + +#ifdef _640x400 + y = (first << 7) + (i << 4) + (j << 1); + if (x & 128) + { + video__wider_int_font[0][y] = + video__wider_int_font[0][y+1] = + video__wider_int_font[1][y] = + video__wider_int_font[1][y+1] = COLOR_LIGHT_GREEN; + video__wider_int_font[2][y] = + video__wider_int_font[2][y+1] = COLOR_LIGHT_RED; + } + else + { + video__wider_int_font[0][y] = + video__wider_int_font[0][y+1] = + video__wider_int_font[2][y] = + video__wider_int_font[2][y+1] = COLOR_BLACK; + video__wider_int_font[1][y] = + video__wider_int_font[1][y+1] = COLOR_MEDIUM_BLUE; + } +#else + y = (first << 6) + (i << 3) + j; + if (x & 128) + { + video__int_font[0][y] = + video__int_font[1][y] = COLOR_LIGHT_GREEN; + video__int_font[2][y] = COLOR_LIGHT_RED; + } + else + { + video__int_font[0][y] = + video__int_font[2][y] = COLOR_BLACK; + video__int_font[1][y] = COLOR_MEDIUM_BLUE; + } +#endif /* _640x400 */ + x <<= 1; + } + } +} + +/* Should probably move this to assembly... */ + +static void c_interface_print_char40_line( + unsigned char **d, unsigned char **s) +{ +#ifdef _640x400 + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/ + *d += SCANSTEP, *s -= 12; + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/ + *d += SCANSTEP, *s += 4; +#else + *((unsigned int *)(*d)) = *((unsigned int *)(*s));/*32bits*/ + *d += 4, *s += 4; + *((unsigned short *)(*d)) = *((unsigned short *)(*s));/*16bits*/ + *d += 2, *s += 2; + *((unsigned char *)(*d)) = *((unsigned char *)(*s));/*8bits*/ + *d += SCANSTEP, *s += 2; +#endif +} + +void video_plotchar( int x, int y, int scheme, unsigned char c ) +{ + int off; + unsigned char *d; + unsigned char *s; + +#ifdef _640x400 + off = y * SCANWIDTH * 16 + x * 14 + 4; + s = video__wider_int_font[scheme] + c * 128; +#else + off = y * 320 * 8 + x * 7 + 1300; + s = video__int_font[scheme] + c * 64; +#endif + d = video__fb1 + off; + + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); + c_interface_print_char40_line(&d,&s); +} diff --git a/src/xvideo.c b/src/xvideo.c new file mode 100644 index 00000000..83c14776 --- /dev/null +++ b/src/xvideo.c @@ -0,0 +1,851 @@ +/* + * Apple // emulator for Linux: X-Windows graphics support + * + * Copyright 1994 Alexander Jean-Claude Bottema + * Copyright 1995 Stephen Lee + * Copyright 1997, 1998 Aaron Culliney + * Copyright 1998, 1999, 2000 Michael Deutschmann + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* MITSHM! */ + + +#include "video.h" +#include "misc.h" +#include "keys.h" + +/* copied from svideo.c (didn't bother to rename!) */ +static unsigned char *svga_GM; +static unsigned char vga_mem_page_0[SCANWIDTH*SCANHEIGHT]; /* page0 framebuffer */ +static unsigned char vga_mem_page_1[SCANWIDTH*SCANHEIGHT]; /* page1 framebuffer */ + +static Display *display; +static Window win; +static GC gc; +static unsigned int width, height; /* window size */ + +static int screen_num; +static Visual* visual; +static XVisualInfo visualinfo; +static XColor colors[256]; +XImage *image; +static Colormap cmap; +XEvent xevent; + +int doShm = 1;/* assume true */ +XShmSegmentInfo xshminfo; +int xshmeventtype; + + +/* ------------------------------------------------------------------------- + video_setpage(p): Switch to screen page p + ------------------------------------------------------------------------- */ +void video_setpage(int p) +{ + if (p == video__current_page) return; + + if (p) + { + memcpy(vga_mem_page_0,svga_GM,SCANWIDTH*SCANHEIGHT); + memcpy(svga_GM,vga_mem_page_1,SCANWIDTH*SCANHEIGHT); + video__current_page = 1; + video__fb1 = vga_mem_page_0; + video__fb2 = svga_GM; + } + else + { + memcpy(vga_mem_page_1,svga_GM,SCANWIDTH*SCANHEIGHT); + memcpy(svga_GM,vga_mem_page_0,SCANWIDTH*SCANHEIGHT); + video__current_page = 0; + video__fb1 = svga_GM; + video__fb2 = vga_mem_page_1; + } +} + +/* + * XShm code influenced from the DOOM source code. + * This tries to find some shared memory to use. It checks for stale segments + * (maybe due to an emulator crash) and tries to remove them or use them. + */ +static void getshm(int size) { + int key = ('a'<<24) | ('p'<<16) | ('p'<<8) | 'l'; + struct shmid_ds shminfo; + int id; + int rc; + int counter=5; + + /* Try to allocate shared memory segment. Use stale segments if any are + * found. + */ + do + { + id = shmget((key_t) key, 0, 0777); + if (id != -1) + { + /* we got someone else's ID. check if it's stale. */ + printf("Found shared memory key=`%c%c%c%c', id=%d\n", + (key & 0xff000000)>>24, + (key & 0xff0000)>>16, + (key & 0xff00)>>8, + (key & 0xff), + id + ); + rc=shmctl(id, IPC_STAT, &shminfo); /* get stats */ + if (!rc) { + /* someone's using the emulator */ + if (shminfo.shm_nattch) { + printf( "User uid=%d, key=`%c%c%c%c' appears to be running " + "the emulator.\n", + shminfo.shm_perm.cuid, + (key & 0xff000000)>>24, + (key & 0xff0000)>>16, + (key & 0xff00)>>8, + (key & 0xff) + ); + ++key; /* increase the key count */ + } + + /* found a stale ID. */ + else { + /* it's my stale ID */ + if (getuid() == shminfo.shm_perm.cuid) { + rc = shmctl(id, IPC_RMID, 0); + if (!rc) + printf("Was able to kill my old shared memory\n"); + else { + perror("shmctl"); + printf("Was NOT able to kill my old shared memory\n"); + } + + id = shmget((key_t)key, size, IPC_CREAT|0777); + if (id == -1) { + perror("shmget"); + printf("Could not get shared memory\n"); + } + + rc=shmctl(id, IPC_STAT, &shminfo); + if (rc) { + perror("shmctl"); + } + + break; + + } + /* not my ID, but maybe we can use it */ + if (size == shminfo.shm_segsz) { + printf( "Will use stale shared memory of uid=%d\n", + shminfo.shm_perm.cuid); + break; + } + /* not my ID, and we can't use it */ + else { + printf( "Can't use stale shared memory belonging to uid=%d, " + "key=`%c%c%c%c', id=%d\n", + shminfo.shm_perm.cuid, + (key & 0xff000000)>>24, + (key & 0xff0000)>>16, + (key & 0xff00)>>8, + (key & 0xff), + id + ); + ++key; + } + } + } + else + { + /* oops. what to do now? */ + perror("shmctl"); + printf( "Could not get stats on key=`%c%c%c%c', id=%d\n", + (key & 0xff000000)>>24, + (key & 0xff0000)>>16, + (key & 0xff00)>>8, + (key & 0xff), + id + ); + ++key; + } + } + else + { + /* no stale ID's */ + id = shmget((key_t)key, size, IPC_CREAT|0777); + if (id == -1) { + perror("shmget"); + printf("Could not get shared memory\n"); + ++key; + } + break; + } + } while (--counter); + + if (!counter) + { + printf( "System has too many stale/used " + "shared memory segments!\n"); + } + + xshminfo.shmid = id; + + /* attach to the shared memory segment */ + image->data = xshminfo.shmaddr = shmat(id, 0, 0); + + if (image->data == -1) { + perror("shmat"); + printf("Could not attach to shared memory\n"); + exit(1); + } + + printf( "Using shared memory key=`%c%c%c%c', id=%d, addr=0x%x\n", + (key & 0xff000000)>>24, + (key & 0xff0000)>>16, + (key & 0xff00)>>8, + (key & 0xff), + id, + (int) (image->data)); +} + + +static void c_initialize_colors() { + static unsigned char col2[ 3 ] = {255,255,255}; + static int firstcall = 1; + int c,i,j; + + if (visualinfo.class == PseudoColor && visualinfo.depth == 8) + { + /* initialize the colormap */ + if (firstcall) { + firstcall = 0; + for (i=0; i<256; i++) { + colors[i].pixel = i; + colors[i].flags = DoRed|DoGreen|DoBlue; + } + } + + /* align the palette for hires graphics */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 3; j++) { + c = (i & 1) ? col2[ j ] : 0; + colors[ j+i*3+32].red = (c<<8) + c; + c = (i & 2) ? col2[ j ] : 0; + colors[ j+i*3+32].green = (c<<8) + c; + c = (i & 4) ? col2[ j ] : 0; + colors[ j+i*3+32].blue = (c<<8) + c; + } + } + colors[ COLOR_FLASHING_BLACK].red = 0; + colors[ COLOR_FLASHING_BLACK].green = 0; + colors[ COLOR_FLASHING_BLACK].blue = 0; + + colors[ COLOR_LIGHT_WHITE].red = (255<<8)|255; + colors[ COLOR_LIGHT_WHITE].green = (255<<8)|255; + colors[ COLOR_LIGHT_WHITE].blue = (255<<8)|255; + + colors[ COLOR_FLASHING_WHITE].red = (255<<8)|255; + colors[ COLOR_FLASHING_WHITE].green = (255<<8)|255; + colors[ COLOR_FLASHING_WHITE].blue = (255<<8)|255; + + colors[0x00].red = 0; colors[0x00].green = 0; + colors[0x00].blue = 0; /* Black */ + colors[0x10].red = 195; colors[0x10].green = 0; + colors[0x10].blue = 48; /* Magenta */ + colors[0x20].red = 0; colors[0x20].green = 0; + colors[0x20].blue = 130; /* Dark Blue */ + colors[0x30].red = 166; colors[0x30].green = 52; + colors[0x30].blue = 170; /* Purple */ + colors[0x40].red = 0; colors[0x40].green = 146; + colors[0x40].blue = 0; /* Dark Green */ + colors[0x50].red = 105; colors[0x50].green = 105; + colors[0x50].blue = 105; /* Dark Grey*/ + colors[0x60].red = 113; colors[0x60].green = 24; + colors[0x60].blue = 255; /* Medium Blue */ + colors[0x70].red = 12; colors[0x70].green = 190; + colors[0x70].blue = 235; /* Light Blue */ + colors[0x80].red = 150; colors[0x80].green = 85; + colors[0x80].blue = 40; /* Brown */ + colors[0x90].red = 255; colors[0xa0].green = 24; + colors[0x90].blue = 44; /* Orange */ + colors[0xa0].red = 150; colors[0xa0].green = 170; + colors[0xa0].blue = 170; /* Light Gray */ + colors[0xb0].red = 255; colors[0xb0].green = 158; + colors[0xb0].blue = 150; /* Pink */ + colors[0xc0].red = 0; colors[0xc0].green = 255; + colors[0xc0].blue = 0; /* Green */ + colors[0xd0].red = 255; colors[0xd0].green = 255; + colors[0xd0].blue = 0; /* Yellow */ + colors[0xe0].red = 130; colors[0xe0].green = 255; + colors[0xe0].blue = 130; /* Aqua */ + colors[0xf0].red = 255; colors[0xf0].green = 255; + colors[0xf0].blue = 255; /* White */ + + /* mirror of lores colors optimized for dhires code */ + colors[0x00].red = 0; colors[0x00].green = 0; + colors[0x00].blue = 0; /* Black */ + colors[0x08].red = 195; colors[0x08].green = 0; + colors[0x08].blue = 48; /* Magenta */ + colors[0x01].red = 0; colors[0x01].green = 0; + colors[0x01].blue = 130; /* Dark Blue */ + colors[0x09].red = 166; colors[0x09].green = 52; + colors[0x09].blue = 170; /* Purple */ + colors[0x02].red = 0; colors[0x02].green = 146; + colors[0x02].blue = 0; /* Dark Green */ + colors[0x0a].red = 105; colors[0x0A].green = 105; + colors[0x0a].blue = 105; /* Dark Grey*/ + colors[0x03].red = 113; colors[0x03].green = 24; + colors[0x03].blue = 255; /* Medium Blue */ + colors[0x0b].red = 12; colors[0x0b].green = 190; + colors[0x0b].blue = 235; /* Light Blue */ + colors[0x04].red = 150; colors[0x04].green = 85; + colors[0x04].blue = 40; /* Brown */ + colors[0x0c].red = 255; colors[0x0c].green = 24; + colors[0x0c].blue = 44; /* Orange */ + colors[0x05].red = 150; colors[0x05].green = 170; + colors[0x05].blue = 170; /* Light Gray */ + colors[0x0d].red = 255; colors[0x0d].green = 158; + colors[0x0d].blue = 150; /* Pink */ + colors[0x06].red = 0; colors[0x06].green = 255; + colors[0x06].blue = 0; /* Green */ + colors[0x0e].red = 255; colors[0x0e].green = 255; + colors[0x0e].blue = 0; /* Yellow */ + colors[0x07].red = 130; colors[0x07].green = 255; + colors[0x07].blue = 130; /* Aqua */ + colors[0x0f].red = 255; colors[0x0f].green = 255; + colors[0x0f].blue = 255; /* White */ + + for (i=0; i<16; i++) { + colors[i].red = (colors[i].red<<8) | colors[i].red; + colors[i].green = (colors[i].green<<8) | colors[i].green; + colors[i].blue = (colors[i].blue<<8) | colors[i].blue; + + colors[i<<4].red = (colors[i<<4].red<<8) | colors[i<<4].red; + colors[i<<4].green = (colors[i<<4].green<<8) | colors[i<<4].green; + colors[i<<4].blue = (colors[i<<4].blue<<8) | colors[i<<4].blue; + } + // store the colors to the current colormap + XStoreColors(display, cmap, colors, 256); + } +} + + +/* HACK: this is incredibly broken. + * Map the X keysyms back into scancodes so the routines in keys.c can deal + * with it. We do this to be compatible with what the SVGAlib version does. + */ +static int keysym_to_scancode(void) { + static int rc = 0xFF; + + switch(rc = XKeycodeToKeysym(display, xevent.xkey.keycode, 0)) + { + case XK_F1: + rc = 59; break; + case XK_F2: + rc = 60; break; + case XK_F3: + rc = 61; break; + case XK_F4: + rc = 62; break; + case XK_F5: + rc = 63; break; + case XK_F6: + rc = 64; break; + case XK_F7: + rc = 65; break; + case XK_F8: + rc = 66; break; + case XK_F9: + rc = 67; break; + case XK_F10: + rc = 68; break; + case XK_Left: + rc = 105; break; + case XK_Right: + rc = 106; break; + case XK_Down: + rc = 108; break; + case XK_Up: + rc = 103; break; + case XK_Escape: + rc = 1; break; + case XK_Return: + rc = 28; break; + case XK_Tab: + rc = 15; break; + case XK_Shift_L: + rc = SCODE_L_SHIFT; break; + case XK_Shift_R: + rc = SCODE_R_SHIFT; break; + case XK_Control_L: + rc = SCODE_L_CTRL; break; + case XK_Control_R: + rc = SCODE_R_CTRL; break; + case XK_Caps_Lock: + rc = SCODE_CAPS; break; + case XK_BackSpace: + rc = 14; break; + case XK_Insert: + rc = 110; break; + case XK_Pause: + rc = 119; break; + case XK_Break: + /* Pause and Break are the same key, but have different + * scancodes (on PC keyboards). Ctrl makes the difference. + * + * We assume the X server is passing along the distinction to us, + * rather than making us check Ctrl manually. + */ + rc = 101; break; + case XK_Print: + rc = 99; break; + case XK_Delete: + rc = 111; break; + case XK_End: + rc = 107; break; + case XK_Home: + rc = 102; break; + case XK_Page_Down: + rc = 109; break; + case XK_Page_Up: + rc = 104; break; + + // keypad joystick movement + case XK_KP_5: + case XK_KP_Begin: + rc = SCODE_J_C; break; + case XK_KP_4: + case XK_KP_Left: + rc = SCODE_J_L; break; + case XK_KP_8: + case XK_KP_Up: + rc = SCODE_J_U; break; + case XK_KP_6: + case XK_KP_Right: + rc = SCODE_J_R; break; + case XK_KP_2: + case XK_KP_Down: + rc = SCODE_J_D; break; + + case XK_Alt_L: + rc = 56; break; + case XK_Alt_R: + rc = 100; break; + + default: + if ((rc >= XK_space) && (rc <= XK_asciitilde)) + rc = xevent.xkey.keycode - 8; + break; + } + + return rc & 0xFF;/* normalize */ +} + +static void post_image() { + if (doShm) { + if (!XShmPutImage( + display, + win, + gc, + image, + 0, 0, + 0, 0, + SCANWIDTH, SCANHEIGHT, + True)) + fprintf(stderr, "XShmPutImage() failed\n"); + } else { + if (XPutImage( + display, + win, + gc, + image, + 0, 0, + 0, 0, + SCANWIDTH, SCANHEIGHT + )) + fprintf(stderr, "XPutImage() failed\n"); + } +} + +static void c_flash_cursor(int on) { + // flash only if it's text or mixed modes. + if (softswitches & (SS_TEXT|SS_MIXED)) { + if (!on) { + colors[ COLOR_FLASHING_BLACK].red = 0; + colors[ COLOR_FLASHING_BLACK].green = 0; + colors[ COLOR_FLASHING_BLACK].blue = 0; + + colors[ COLOR_FLASHING_WHITE].red = 0xffff; + colors[ COLOR_FLASHING_WHITE].green = 0xffff; + colors[ COLOR_FLASHING_WHITE].blue = 0xffff; + } else { + colors[ COLOR_FLASHING_WHITE].red = 0; + colors[ COLOR_FLASHING_WHITE].green = 0; + colors[ COLOR_FLASHING_WHITE].blue = 0; + + colors[ COLOR_FLASHING_BLACK].red = 0xffff; + colors[ COLOR_FLASHING_BLACK].green = 0xffff; + colors[ COLOR_FLASHING_BLACK].blue = 0xffff; + } + + // store the colors to the current colormap + XStoreColors(display, cmap, colors, 256); + } +} + +/* FIXME: blocking not implemented... */ +void video_sync(int block) { + static int flash_count = 0; + // post the image and loop waiting for it to finish and + // also process other input events + post_image(); +LOOP: + if (doShm) + XNextEvent( + display, + &xevent); + else if (!XCheckMaskEvent( + display, + KeyPressMask|KeyReleaseMask, + &xevent)) + goto POLL_FINISHED; + switch (xevent.type) { + case KeyPress: + c_read_raw_key(keysym_to_scancode(), 1); + break; + case KeyRelease: + c_read_raw_key(keysym_to_scancode(), 0); + break; + default: + if (xevent.type == xshmeventtype) + goto POLL_FINISHED; + break; + } + goto LOOP; + +POLL_FINISHED: + + switch (++flash_count) + { + case 6: + c_flash_cursor(1); + break; + case 12: + c_flash_cursor(0); + flash_count = 0; + break; + default: + break; + } +} + +static Cursor hidecursor() { + Pixmap cursormask; + XGCValues xgc; + XColor dummycolour; + Cursor cursor; + + cursormask = XCreatePixmap(display, win, 1, 1, 1/*depth*/); + xgc.function = GXclear; + gc = XCreateGC(display, cursormask, GCFunction, &xgc); + XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + cursor = XCreatePixmapCursor(display, cursormask, cursormask, + &dummycolour,&dummycolour, 0,0); + XFreePixmap(display,cursormask); + XFreeGC(display,gc); + return cursor; +} + +static void parseArgs() { + int i; + for (i=0; iflags = PPosition | PSize | PMinSize | PMaxSize; + size_hints->min_width = width; + size_hints->min_height = height; + size_hints->max_width = width; + size_hints->max_height = height; + + /* store window_name and icon_name for niceity. */ + if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) { + fprintf(stderr, "structure allocation for windowName failed.\n"); + exit(1); + } + + if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) { + fprintf(stderr, "structure allocation for iconName failed.\n"); + exit(1); + } + + wm_hints->initial_state = NormalState; + wm_hints->input = True; + wm_hints->flags = StateHint | IconPixmapHint/* | InputHint*/; + + class_hints->res_name = progname; + class_hints->res_class = "Apple2"; + + XSetWMProperties(display, win, &windowName, &iconName, + argv, argc, size_hints, wm_hints, + class_hints); + + XDefineCursor(display, win, hidecursor(display, win)); + + /* create the GC */ + valuemask = GCGraphicsExposures; + xgcvalues.graphics_exposures = False; + gc = XCreateGC( + display, + win, + valuemask, + &xgcvalues); + + /* display window */ + XMapWindow(display, win); + + /* wait until it is OK to draw */ + drawingok = 0; + while (!drawingok) + { + XNextEvent(display, &xevent); + if ((xevent.type == Expose) && !xevent.xexpose.count) + { + drawingok = 1; + } + } + + xshmeventtype = XShmGetEventBase(display) + ShmCompletion; + + /* create the image */ + if (doShm) { + image = XShmCreateImage( + display, + visual, + 8, + ZPixmap, + 0, + &xshminfo, + SCANWIDTH, + SCANHEIGHT); + + if (!image) { + fprintf(stderr, "XShmCreateImage failed\n"); + exit(1); + } + + printf("Allocating shared memory %dx%d region\n", + image->bytes_per_line, image->height); + + getshm(image->bytes_per_line * image->height); + + /* get the X server to attach to it */ + if (!XShmAttach(display, &xshminfo)) { + fprintf(stderr, "XShmAttach() failed in InitGraphics()\n"); + exit(1); + } + } else { + char *data = malloc(SCANWIDTH*SCANHEIGHT*sizeof(unsigned char)); + if (!data) { + fprintf(stderr, "no memory for image data!\n"); + exit(1); + } + printf("Creating regular XImage\n"); + image = XCreateImage( + display, + visual, + 8, + ZPixmap, + 0, + data, + SCANWIDTH, + SCANHEIGHT, + 8/*bitmap_pad*/, + SCANWIDTH/*bytes_per_line*/); + + if (!image) { + fprintf(stderr, "XCreateImage failed\n"); + exit(1); + } + + } + + svga_GM = video__fb1 = image->data; + video__fb2 = vga_mem_page_1; + + memset(video__fb1,0,SCANWIDTH*SCANHEIGHT); + memset(video__fb2,0,SCANWIDTH*SCANHEIGHT); + +} + +void video_shutdown(void) +{ + if (doShm) { + // Detach from X server + if (!XShmDetach(display, &xshminfo)) + fprintf(stderr,"XShmDetach() failed in video_shutdown()\n"); + + // Release shared memory. + shmdt(xshminfo.shmaddr); + shmctl(xshminfo.shmid, IPC_RMID, 0); + + // Paranoia. + image->data = NULL; + } else { + free(image->data); + } + + exit(0); +}