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