PCem

changeset 0:bba9a2b71a78

Add v0.7 source
author TomW
date Sun Apr 21 14:54:35 2013 +0100
parents
children fb4a67daaa1b
files COPYING acer386.nvr ami286.nvr ami386.nvr ami486.nvr at.nvr cmdpc30.nvr dell200.nvr europc.nvr hot-433.nvr mda.rom megapc.nvr pc1512.nvr pc1640.nvr pc2086.nvr pc3086.nvr readme.txt roms/acer386/roms.txt roms/ami286/roms.txt roms/ami386/roms.txt roms/ami486/roms.txt roms/cmdpc30/roms.txt roms/dells200/roms.txt roms/dtk/roms.txt roms/europc/roms.txt roms/genxt/roms.txt roms/hot-433/roms.txt roms/ibmat/roms.txt roms/ibmpc/roms.txt roms/ibmxt/roms.txt roms/megapc/roms.txt roms/olivetti_m24/roms.txt roms/pc1512/roms.txt roms/pc1640/roms.txt roms/pc200/roms.txt roms/pc2086/roms.txt roms/pc3086/roms.txt roms/tandy/roms.txt roms/win486/roms.txt src/286.c src/386.c src/Makefile.mingw src/acer386sx.c src/acer386sx.h src/adlib.c src/ali1429.c src/ali1429.h src/amstrad.c src/amstrad.h src/cdrom-ioctl.c src/cdrom-ioctl.h src/cms.c src/config.c src/config.h src/cpu.c src/cpu.h src/dac.c src/dma.c src/dma.h src/ega.c src/fdc.c src/fdc.h src/filters.h src/gus.c src/harddisk.c src/headland.c src/headland.h src/ibm.h src/ide.c src/ide.h src/io.c src/io.h src/jim.c src/jim.h src/keyboard.c src/keyboard.h src/keyboard_amstrad.c src/keyboard_amstrad.h src/keyboard_at.c src/keyboard_at.h src/keyboard_olim24.c src/keyboard_olim24.h src/keyboard_xt.c src/keyboard_xt.h src/lpt.c src/lpt.h src/mame/fmopl.c src/mame/fmopl.h src/mame/ymf262.c src/mame/ymf262.h src/mcr.c src/mem.c src/mem.h src/model.c src/model.h src/mouse.c src/mouse.h src/mouse_ps2.c src/mouse_ps2.h src/mouse_serial.c src/mouse_serial.h src/neat.c src/neat.h src/nvr.c src/nvr.h src/olivetti_m24.c src/olivetti_m24.h src/opti.c src/pc.c src/pc.rc src/pci.c src/pci.h src/pic.c src/pic.h src/pit.c src/pit.h src/plat-dinput.h src/plat-keyboard.h src/plat-mouse.h src/ppi.c src/ppi.h src/psg.c src/psg.h src/resources.h src/sblaster.c src/serial.c src/serial.h src/sound.c src/sound.h src/soundopenal.c src/um8881f.c src/um8881f.h src/vid_cga.c src/vid_cga.h src/vid_ega.c src/vid_ega.h src/vid_et4000.c src/vid_et4000w32.c src/vid_et4000w32i.c src/vid_hercules.c src/vid_icd2061.c src/vid_icd2061.h src/vid_mda.c src/vid_olivetti_m24.c src/vid_olivetti_m24.h src/vid_oti067.c src/vid_paradise.c src/vid_pc1512.c src/vid_pc1640.c src/vid_pc200.c src/vid_s3.c src/vid_sdac_ramdac.c src/vid_sdac_ramdac.h src/vid_stg_ramdac.c src/vid_stg_ramdac.h src/vid_svga.c src/vid_svga.h src/vid_tandy.c src/vid_tkd8001_ramdac.c src/vid_tkd8001_ramdac.h src/vid_tvga.c src/vid_unk_ramdac.c src/vid_unk_ramdac.h src/video.c src/video.h src/wd76c10.c src/wd76c10.h src/win-d3d.cc src/win-d3d.h src/win-ddraw.cc src/win-ddraw.h src/win-keyboard.cc src/win-mouse.cc src/win-opengl.c src/win-opengl.h src/win-timer.c src/win-video.c src/win.c src/win.h src/x86.c src/x86.h src/x86_flags.h src/x86seg.c src/x87.c src/x87.h src/xtide.c src/xtide.h win486.nvr
diffstat 187 files changed, 52566 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/COPYING	Sun Apr 21 14:54:35 2013 +0100
     1.3 @@ -0,0 +1,339 @@
     1.4 +		    GNU GENERAL PUBLIC LICENSE
     1.5 +		       Version 2, June 1991
     1.6 +
     1.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
     1.8 +                          675 Mass Ave, Cambridge, MA 02139, USA
     1.9 + Everyone is permitted to copy and distribute verbatim copies
    1.10 + of this license document, but changing it is not allowed.
    1.11 +
    1.12 +			    Preamble
    1.13 +
    1.14 +  The licenses for most software are designed to take away your
    1.15 +freedom to share and change it.  By contrast, the GNU General Public
    1.16 +License is intended to guarantee your freedom to share and change free
    1.17 +software--to make sure the software is free for all its users.  This
    1.18 +General Public License applies to most of the Free Software
    1.19 +Foundation's software and to any other program whose authors commit to
    1.20 +using it.  (Some other Free Software Foundation software is covered by
    1.21 +the GNU Library General Public License instead.)  You can apply it to
    1.22 +your programs, too.
    1.23 +
    1.24 +  When we speak of free software, we are referring to freedom, not
    1.25 +price.  Our General Public Licenses are designed to make sure that you
    1.26 +have the freedom to distribute copies of free software (and charge for
    1.27 +this service if you wish), that you receive source code or can get it
    1.28 +if you want it, that you can change the software or use pieces of it
    1.29 +in new free programs; and that you know you can do these things.
    1.30 +
    1.31 +  To protect your rights, we need to make restrictions that forbid
    1.32 +anyone to deny you these rights or to ask you to surrender the rights.
    1.33 +These restrictions translate to certain responsibilities for you if you
    1.34 +distribute copies of the software, or if you modify it.
    1.35 +
    1.36 +  For example, if you distribute copies of such a program, whether
    1.37 +gratis or for a fee, you must give the recipients all the rights that
    1.38 +you have.  You must make sure that they, too, receive or can get the
    1.39 +source code.  And you must show them these terms so they know their
    1.40 +rights.
    1.41 +
    1.42 +  We protect your rights with two steps: (1) copyright the software, and
    1.43 +(2) offer you this license which gives you legal permission to copy,
    1.44 +distribute and/or modify the software.
    1.45 +
    1.46 +  Also, for each author's protection and ours, we want to make certain
    1.47 +that everyone understands that there is no warranty for this free
    1.48 +software.  If the software is modified by someone else and passed on, we
    1.49 +want its recipients to know that what they have is not the original, so
    1.50 +that any problems introduced by others will not reflect on the original
    1.51 +authors' reputations.
    1.52 +
    1.53 +  Finally, any free program is threatened constantly by software
    1.54 +patents.  We wish to avoid the danger that redistributors of a free
    1.55 +program will individually obtain patent licenses, in effect making the
    1.56 +program proprietary.  To prevent this, we have made it clear that any
    1.57 +patent must be licensed for everyone's free use or not licensed at all.
    1.58 +
    1.59 +  The precise terms and conditions for copying, distribution and
    1.60 +modification follow.
    1.61 +
    1.62 +		    GNU GENERAL PUBLIC LICENSE
    1.63 +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    1.64 +
    1.65 +  0. This License applies to any program or other work which contains
    1.66 +a notice placed by the copyright holder saying it may be distributed
    1.67 +under the terms of this General Public License.  The "Program", below,
    1.68 +refers to any such program or work, and a "work based on the Program"
    1.69 +means either the Program or any derivative work under copyright law:
    1.70 +that is to say, a work containing the Program or a portion of it,
    1.71 +either verbatim or with modifications and/or translated into another
    1.72 +language.  (Hereinafter, translation is included without limitation in
    1.73 +the term "modification".)  Each licensee is addressed as "you".
    1.74 +
    1.75 +Activities other than copying, distribution and modification are not
    1.76 +covered by this License; they are outside its scope.  The act of
    1.77 +running the Program is not restricted, and the output from the Program
    1.78 +is covered only if its contents constitute a work based on the
    1.79 +Program (independent of having been made by running the Program).
    1.80 +Whether that is true depends on what the Program does.
    1.81 +
    1.82 +  1. You may copy and distribute verbatim copies of the Program's
    1.83 +source code as you receive it, in any medium, provided that you
    1.84 +conspicuously and appropriately publish on each copy an appropriate
    1.85 +copyright notice and disclaimer of warranty; keep intact all the
    1.86 +notices that refer to this License and to the absence of any warranty;
    1.87 +and give any other recipients of the Program a copy of this License
    1.88 +along with the Program.
    1.89 +
    1.90 +You may charge a fee for the physical act of transferring a copy, and
    1.91 +you may at your option offer warranty protection in exchange for a fee.
    1.92 +
    1.93 +  2. You may modify your copy or copies of the Program or any portion
    1.94 +of it, thus forming a work based on the Program, and copy and
    1.95 +distribute such modifications or work under the terms of Section 1
    1.96 +above, provided that you also meet all of these conditions:
    1.97 +
    1.98 +    a) You must cause the modified files to carry prominent notices
    1.99 +    stating that you changed the files and the date of any change.
   1.100 +
   1.101 +    b) You must cause any work that you distribute or publish, that in
   1.102 +    whole or in part contains or is derived from the Program or any
   1.103 +    part thereof, to be licensed as a whole at no charge to all third
   1.104 +    parties under the terms of this License.
   1.105 +
   1.106 +    c) If the modified program normally reads commands interactively
   1.107 +    when run, you must cause it, when started running for such
   1.108 +    interactive use in the most ordinary way, to print or display an
   1.109 +    announcement including an appropriate copyright notice and a
   1.110 +    notice that there is no warranty (or else, saying that you provide
   1.111 +    a warranty) and that users may redistribute the program under
   1.112 +    these conditions, and telling the user how to view a copy of this
   1.113 +    License.  (Exception: if the Program itself is interactive but
   1.114 +    does not normally print such an announcement, your work based on
   1.115 +    the Program is not required to print an announcement.)
   1.116 +
   1.117 +These requirements apply to the modified work as a whole.  If
   1.118 +identifiable sections of that work are not derived from the Program,
   1.119 +and can be reasonably considered independent and separate works in
   1.120 +themselves, then this License, and its terms, do not apply to those
   1.121 +sections when you distribute them as separate works.  But when you
   1.122 +distribute the same sections as part of a whole which is a work based
   1.123 +on the Program, the distribution of the whole must be on the terms of
   1.124 +this License, whose permissions for other licensees extend to the
   1.125 +entire whole, and thus to each and every part regardless of who wrote it.
   1.126 +
   1.127 +Thus, it is not the intent of this section to claim rights or contest
   1.128 +your rights to work written entirely by you; rather, the intent is to
   1.129 +exercise the right to control the distribution of derivative or
   1.130 +collective works based on the Program.
   1.131 +
   1.132 +In addition, mere aggregation of another work not based on the Program
   1.133 +with the Program (or with a work based on the Program) on a volume of
   1.134 +a storage or distribution medium does not bring the other work under
   1.135 +the scope of this License.
   1.136 +
   1.137 +  3. You may copy and distribute the Program (or a work based on it,
   1.138 +under Section 2) in object code or executable form under the terms of
   1.139 +Sections 1 and 2 above provided that you also do one of the following:
   1.140 +
   1.141 +    a) Accompany it with the complete corresponding machine-readable
   1.142 +    source code, which must be distributed under the terms of Sections
   1.143 +    1 and 2 above on a medium customarily used for software interchange; or,
   1.144 +
   1.145 +    b) Accompany it with a written offer, valid for at least three
   1.146 +    years, to give any third party, for a charge no more than your
   1.147 +    cost of physically performing source distribution, a complete
   1.148 +    machine-readable copy of the corresponding source code, to be
   1.149 +    distributed under the terms of Sections 1 and 2 above on a medium
   1.150 +    customarily used for software interchange; or,
   1.151 +
   1.152 +    c) Accompany it with the information you received as to the offer
   1.153 +    to distribute corresponding source code.  (This alternative is
   1.154 +    allowed only for noncommercial distribution and only if you
   1.155 +    received the program in object code or executable form with such
   1.156 +    an offer, in accord with Subsection b above.)
   1.157 +
   1.158 +The source code for a work means the preferred form of the work for
   1.159 +making modifications to it.  For an executable work, complete source
   1.160 +code means all the source code for all modules it contains, plus any
   1.161 +associated interface definition files, plus the scripts used to
   1.162 +control compilation and installation of the executable.  However, as a
   1.163 +special exception, the source code distributed need not include
   1.164 +anything that is normally distributed (in either source or binary
   1.165 +form) with the major components (compiler, kernel, and so on) of the
   1.166 +operating system on which the executable runs, unless that component
   1.167 +itself accompanies the executable.
   1.168 +
   1.169 +If distribution of executable or object code is made by offering
   1.170 +access to copy from a designated place, then offering equivalent
   1.171 +access to copy the source code from the same place counts as
   1.172 +distribution of the source code, even though third parties are not
   1.173 +compelled to copy the source along with the object code.
   1.174 +
   1.175 +  4. You may not copy, modify, sublicense, or distribute the Program
   1.176 +except as expressly provided under this License.  Any attempt
   1.177 +otherwise to copy, modify, sublicense or distribute the Program is
   1.178 +void, and will automatically terminate your rights under this License.
   1.179 +However, parties who have received copies, or rights, from you under
   1.180 +this License will not have their licenses terminated so long as such
   1.181 +parties remain in full compliance.
   1.182 +
   1.183 +  5. You are not required to accept this License, since you have not
   1.184 +signed it.  However, nothing else grants you permission to modify or
   1.185 +distribute the Program or its derivative works.  These actions are
   1.186 +prohibited by law if you do not accept this License.  Therefore, by
   1.187 +modifying or distributing the Program (or any work based on the
   1.188 +Program), you indicate your acceptance of this License to do so, and
   1.189 +all its terms and conditions for copying, distributing or modifying
   1.190 +the Program or works based on it.
   1.191 +
   1.192 +  6. Each time you redistribute the Program (or any work based on the
   1.193 +Program), the recipient automatically receives a license from the
   1.194 +original licensor to copy, distribute or modify the Program subject to
   1.195 +these terms and conditions.  You may not impose any further
   1.196 +restrictions on the recipients' exercise of the rights granted herein.
   1.197 +You are not responsible for enforcing compliance by third parties to
   1.198 +this License.
   1.199 +
   1.200 +  7. If, as a consequence of a court judgment or allegation of patent
   1.201 +infringement or for any other reason (not limited to patent issues),
   1.202 +conditions are imposed on you (whether by court order, agreement or
   1.203 +otherwise) that contradict the conditions of this License, they do not
   1.204 +excuse you from the conditions of this License.  If you cannot
   1.205 +distribute so as to satisfy simultaneously your obligations under this
   1.206 +License and any other pertinent obligations, then as a consequence you
   1.207 +may not distribute the Program at all.  For example, if a patent
   1.208 +license would not permit royalty-free redistribution of the Program by
   1.209 +all those who receive copies directly or indirectly through you, then
   1.210 +the only way you could satisfy both it and this License would be to
   1.211 +refrain entirely from distribution of the Program.
   1.212 +
   1.213 +If any portion of this section is held invalid or unenforceable under
   1.214 +any particular circumstance, the balance of the section is intended to
   1.215 +apply and the section as a whole is intended to apply in other
   1.216 +circumstances.
   1.217 +
   1.218 +It is not the purpose of this section to induce you to infringe any
   1.219 +patents or other property right claims or to contest validity of any
   1.220 +such claims; this section has the sole purpose of protecting the
   1.221 +integrity of the free software distribution system, which is
   1.222 +implemented by public license practices.  Many people have made
   1.223 +generous contributions to the wide range of software distributed
   1.224 +through that system in reliance on consistent application of that
   1.225 +system; it is up to the author/donor to decide if he or she is willing
   1.226 +to distribute software through any other system and a licensee cannot
   1.227 +impose that choice.
   1.228 +
   1.229 +This section is intended to make thoroughly clear what is believed to
   1.230 +be a consequence of the rest of this License.
   1.231 +
   1.232 +  8. If the distribution and/or use of the Program is restricted in
   1.233 +certain countries either by patents or by copyrighted interfaces, the
   1.234 +original copyright holder who places the Program under this License
   1.235 +may add an explicit geographical distribution limitation excluding
   1.236 +those countries, so that distribution is permitted only in or among
   1.237 +countries not thus excluded.  In such case, this License incorporates
   1.238 +the limitation as if written in the body of this License.
   1.239 +
   1.240 +  9. The Free Software Foundation may publish revised and/or new versions
   1.241 +of the General Public License from time to time.  Such new versions will
   1.242 +be similar in spirit to the present version, but may differ in detail to
   1.243 +address new problems or concerns.
   1.244 +
   1.245 +Each version is given a distinguishing version number.  If the Program
   1.246 +specifies a version number of this License which applies to it and "any
   1.247 +later version", you have the option of following the terms and conditions
   1.248 +either of that version or of any later version published by the Free
   1.249 +Software Foundation.  If the Program does not specify a version number of
   1.250 +this License, you may choose any version ever published by the Free Software
   1.251 +Foundation.
   1.252 +
   1.253 +  10. If you wish to incorporate parts of the Program into other free
   1.254 +programs whose distribution conditions are different, write to the author
   1.255 +to ask for permission.  For software which is copyrighted by the Free
   1.256 +Software Foundation, write to the Free Software Foundation; we sometimes
   1.257 +make exceptions for this.  Our decision will be guided by the two goals
   1.258 +of preserving the free status of all derivatives of our free software and
   1.259 +of promoting the sharing and reuse of software generally.
   1.260 +
   1.261 +			    NO WARRANTY
   1.262 +
   1.263 +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
   1.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
   1.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
   1.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
   1.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   1.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
   1.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
   1.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
   1.271 +REPAIR OR CORRECTION.
   1.272 +
   1.273 +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
   1.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
   1.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
   1.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
   1.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
   1.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
   1.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
   1.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
   1.281 +POSSIBILITY OF SUCH DAMAGES.
   1.282 +
   1.283 +		     END OF TERMS AND CONDITIONS
   1.284 +
   1.285 +	Appendix: How to Apply These Terms to Your New Programs
   1.286 +
   1.287 +  If you develop a new program, and you want it to be of the greatest
   1.288 +possible use to the public, the best way to achieve this is to make it
   1.289 +free software which everyone can redistribute and change under these terms.
   1.290 +
   1.291 +  To do so, attach the following notices to the program.  It is safest
   1.292 +to attach them to the start of each source file to most effectively
   1.293 +convey the exclusion of warranty; and each file should have at least
   1.294 +the "copyright" line and a pointer to where the full notice is found.
   1.295 +
   1.296 +    <one line to give the program's name and a brief idea of what it does.>
   1.297 +    Copyright (C) 19yy  <name of author>
   1.298 +
   1.299 +    This program is free software; you can redistribute it and/or modify
   1.300 +    it under the terms of the GNU General Public License as published by
   1.301 +    the Free Software Foundation; either version 2 of the License, or
   1.302 +    (at your option) any later version.
   1.303 +
   1.304 +    This program is distributed in the hope that it will be useful,
   1.305 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.306 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.307 +    GNU General Public License for more details.
   1.308 +
   1.309 +    You should have received a copy of the GNU General Public License
   1.310 +    along with this program; if not, write to the Free Software
   1.311 +    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   1.312 +
   1.313 +Also add information on how to contact you by electronic and paper mail.
   1.314 +
   1.315 +If the program is interactive, make it output a short notice like this
   1.316 +when it starts in an interactive mode:
   1.317 +
   1.318 +    Gnomovision version 69, Copyright (C) 19yy name of author
   1.319 +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
   1.320 +    This is free software, and you are welcome to redistribute it
   1.321 +    under certain conditions; type `show c' for details.
   1.322 +
   1.323 +The hypothetical commands `show w' and `show c' should show the appropriate
   1.324 +parts of the General Public License.  Of course, the commands you use may
   1.325 +be called something other than `show w' and `show c'; they could even be
   1.326 +mouse-clicks or menu items--whatever suits your program.
   1.327 +
   1.328 +You should also get your employer (if you work as a programmer) or your
   1.329 +school, if any, to sign a "copyright disclaimer" for the program, if
   1.330 +necessary.  Here is a sample; alter the names:
   1.331 +
   1.332 +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
   1.333 +  `Gnomovision' (which makes passes at compilers) written by James Hacker.
   1.334 +
   1.335 +  <signature of Ty Coon>, 1 April 1989
   1.336 +  Ty Coon, President of Vice
   1.337 +
   1.338 +This General Public License does not permit incorporating your program into
   1.339 +proprietary programs.  If your program is a subroutine library, you may
   1.340 +consider it more useful to permit linking proprietary applications with the
   1.341 +library.  If this is what you want to do, use the GNU Library General
   1.342 +Public License instead of this License.
     2.1 Binary file acer386.nvr has changed
     3.1 Binary file ami286.nvr has changed
     4.1 Binary file ami386.nvr has changed
     5.1 Binary file ami486.nvr has changed
     6.1 Binary file at.nvr has changed
     7.1 Binary file cmdpc30.nvr has changed
     8.1 Binary file dell200.nvr has changed
     9.1 Binary file europc.nvr has changed
    10.1 Binary file hot-433.nvr has changed
    11.1 Binary file mda.rom has changed
    12.1 Binary file megapc.nvr has changed
    13.1 Binary file pc1512.nvr has changed
    14.1 Binary file pc1640.nvr has changed
    15.1 Binary file pc2086.nvr has changed
    16.1 Binary file pc3086.nvr has changed
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/readme.txt	Sun Apr 21 14:54:35 2013 +0100
    17.3 @@ -0,0 +1,483 @@
    17.4 +PCem v0.7
    17.5 +
    17.6 +Changes since v0.6:
    17.7 +
    17.8 +- New machines - DTK XT clone, Amstrad PC2086, Amstrad PC3086, Olivetti M24, Commodore PC 30 III, 
    17.9 +  PCI 486 clone
   17.10 +- New graphics cards - IBM EGA, Diamond Stealth 32 (ET4000/W32p), Paradise Bahamas 64 (S3 Vision864)
   17.11 +- IDE hard disc emulation. This replaces the old INT 13 trapping emulation on all models. For machines
   17.12 +  which don't natively have IDE support, the XTIDE board is emulated. See the readme file for details.
   17.13 +- Fixed wrong code segment on page fault - eliminates some Win95 crashes
   17.14 +- Fixed trap flag on POPF/IRET - improves DOS box on Win95
   17.15 +- Fixed various pmode stuff, OS/2 v1.3 works
   17.16 +- Fixed MMU caching bug, Win95 more stable, IE4 now works, Win98 now works, Linux now appears to work
   17.17 +- Major improvements to floppy disc emulation - fixed occasional disc corruption, works with OS/2 and Linux
   17.18 +- ATAPI identify command now returns an ATAPI version, Win95 native CD-ROM drivers now work.
   17.19 +- CD-ROM emulation now uses raw read for audio - works on Windows 7
   17.20 +- Major internal changes to graphics emulation
   17.21 +- Major internal changes to memory and IO emulation
   17.22 +- Many other changes
   17.23 +
   17.24 +
   17.25 +PCem emulates the following machines:
   17.26 +
   17.27 +IBM 5150 PC (1981) 
   17.28 +The original PC. This shipped in 1981 with a 4.77mhz 8088, 64k of RAM, and a cassette port.
   17.29 +Disc drives quickly became standard, along with more memory.
   17.30 +
   17.31 +ROM files needed:
   17.32 +
   17.33 +pc102782.bin
   17.34 +basicc11.f6
   17.35 +basicc11.f8
   17.36 +basicc11.fa
   17.37 +basicc11.fc
   17.38 +
   17.39 +
   17.40 +IBM 5160 XT (1983)
   17.41 +From a hardware perspective, this is a minor tweak of the original PC. It originally shipped
   17.42 +with 128k of RAM and a 10mb hard disc, both of which could be easily fitted to the 1981 machine.
   17.43 +However, this was targetted as businesses and was more successful than the original.
   17.44 +
   17.45 +ROM files needed:
   17.46 +
   17.47 +xt050986.0
   17.48 +xt050986.1
   17.49 +
   17.50 +
   17.51 +IBM AT (1984)
   17.52 +This was the 'next generation' PC, fully 16-bit with an 80286. The original model came with a 6mhz
   17.53 +286, which ran three times as fast as the XT. This model also introduced EGA.
   17.54 +
   17.55 +ROM files needed:
   17.56 +
   17.57 +at111585.0
   17.58 +at111585.1
   17.59 +
   17.60 +
   17.61 +Olivetti M24 (1984)
   17.62 +An enhanced XT clone, also known as the AT&T PC 6300. Has an 8086 CPU, and an unusual 'double-res'
   17.63 +CGA display.
   17.64 +
   17.65 +ROM files needed:
   17.66 +
   17.67 +olivetti_m24_version_1.43_low.bin
   17.68 +olivetti_m24_version_1.43_high.bin
   17.69 +
   17.70 +
   17.71 +Tandy 1000 (1985)
   17.72 +This is a clone of the unsuccessful IBM PCjr, which added better graphics and sound to the XT,
   17.73 +but removed much expandability plus some other hardware (such as the DMA controller). The Tandy
   17.74 +puts back the DMA controller and ISA slots, making it a much more useful machine. Many games
   17.75 +from the late 80s support the Tandy.
   17.76 +
   17.77 +ROM files needed:
   17.78 +
   17.79 +tandy1t1.020
   17.80 +
   17.81 +
   17.82 +DTK Clone XT (1986)
   17.83 +A generic clone XT board.
   17.84 +
   17.85 +ROM files needed:
   17.86 +
   17.87 +DTK_ERSO_2.42_2764.bin
   17.88 +
   17.89 +
   17.90 +Amstrad PC1512 (1986)
   17.91 +This was Amstrad's first entry into the PC clone market (after the CPC and PCW machines), and
   17.92 +was the first cheap PC available in the UK, selling for only £500. It was a 'turbo' clone, 
   17.93 +having an 8mhz 8086, as opposed to an 8088, and had 512k RAM as standard. It also had a 
   17.94 +perculiar modification to its onboard CGA controller - the 640x200 mode had 16 colours instead
   17.95 +of the usual 2. This was put to good use by GEM, which shipped with the machine.
   17.96 +
   17.97 +Amstrad's CGA implementation has a few oddities, these are emulated as best as possible. This
   17.98 +mainly affects games defining unusual video modes, though 160x100x16 still works (as on the real
   17.99 +machine).
  17.100 +
  17.101 +ROM files needed:
  17.102 +
  17.103 +40043.v1
  17.104 +40044.v2
  17.105 +40078.ic127
  17.106 +
  17.107 +
  17.108 +Amstrad PC1640 (1987)
  17.109 +Amstrad's followup to the PC1512, the PC1640 had 640k of RAM and onboard EGA, but was otherwise
  17.110 +mostly the same.
  17.111 +
  17.112 +ROM files needed:
  17.113 +
  17.114 +40043.v3
  17.115 +40044.v3
  17.116 +40100
  17.117 +
  17.118 +
  17.119 +Sinclair PC200/Amstrad PC20 (1988)
  17.120 +This was Amstrad's entry to the 16-bit home computer market, intended to compete with the Atari
  17.121 +ST and Commodore Amiga. It's similar to the PC1512, but is based on Amstrad's portable PPC512
  17.122 +system. With stock CGA and PC speaker, it couldn't compare with the ST or Amiga.
  17.123 +
  17.124 +ROM files needed:
  17.125 +
  17.126 +pc20v2.0
  17.127 +pc20v2.1
  17.128 +40109.bin
  17.129 +
  17.130 +
  17.131 +Schneider Euro PC (1988)
  17.132 +A German XT clone. An 'all-in-one' system like the Sinclair PC200. I don't know much about this
  17.133 +machine to be honest! This doesn't appear to work with the XTIDE BIOS, so therefore this is the
  17.134 +only model that does not support hard discs.
  17.135 +
  17.136 +ROM files needed:
  17.137 +
  17.138 +50145
  17.139 +50146
  17.140 +
  17.141 +
  17.142 +(c)Anonymous Generic Turbo XT BIOS (1988?)
  17.143 +This is a BIOS whose source code was made available on Usenet in 1988. It appears to be an 
  17.144 +anonymous BIOS from an XT clone board. It was then heavily modified to fix bugs. The history of
  17.145 +this BIOS (and the source code) is at http://dizzie.narod.ru/bios.txt
  17.146 +
  17.147 +ROM files needed:
  17.148 +
  17.149 +pcxt.rom
  17.150 +
  17.151 +
  17.152 +Commodore PC30-III (1988)
  17.153 +A fairly generic 286 clone.
  17.154 +
  17.155 +ROM files needed:
  17.156 +
  17.157 +commodore pc 30 iii even.bin
  17.158 +commodore pc 30 iii odd.bin
  17.159 +
  17.160 +
  17.161 +Amstrad PC2086 (1989)
  17.162 +The PC2086 is essentially a PC1640 with VGA and 3.5" floppy drives.
  17.163 +
  17.164 +ROM files needed:
  17.165 +
  17.166 +40179.ic129
  17.167 +40180.ic132
  17.168 +40186.ic171
  17.169 +
  17.170 +
  17.171 +Amstrad PC3086 (1990)
  17.172 +The PC3086 is a version of the PC2086 with a more standard case.
  17.173 +
  17.174 +ROM files needed:
  17.175 +
  17.176 +fc00.bin
  17.177 +c000.bin
  17.178 +
  17.179 +
  17.180 +Dell System 200 (1990?)
  17.181 +This is a pretty generic 286 clone with a Phoenix BIOS.
  17.182 +
  17.183 +HIMEM.SYS doesn't appear to work on this one, for some reason.
  17.184 +
  17.185 +ROM files needed:
  17.186 +
  17.187 +dell0.bin
  17.188 +dell1.bin
  17.189 +
  17.190 +
  17.191 +AMI 286 clone (1990)
  17.192 +This is a generic 286 clone with an AMI BIOS.
  17.193 +
  17.194 +ROM files needed:
  17.195 +
  17.196 +amic206.bin
  17.197 +
  17.198 +
  17.199 +Acermate 386SX/25N (1992?)
  17.200 +An integrated 386SX clone, with onboard Oak SVGA and IO.
  17.201 +
  17.202 +ROM files needed:
  17.203 +acer386.bin
  17.204 +oti067.bin
  17.205 +
  17.206 +
  17.207 +Amstrad MegaPC (1992)
  17.208 +A 386SX clone (otherwise known as the PC7386SX) with a built-in Sega Megadrive. Only the PC section
  17.209 +is emulated, obv.
  17.210 +
  17.211 +ROM files needed:
  17.212 +41651-bios lo.u18
  17.213 +211253-bios hi.u19
  17.214 +
  17.215 +
  17.216 +AMI 386 clone (1994)
  17.217 +This is a generic 386 clone with an AMI BIOS. The BIOS came from my 386DX/40, the motherboard is
  17.218 +dated June 1994.
  17.219 +
  17.220 +ROM files needed:
  17.221 +
  17.222 +ami495.bin
  17.223 +
  17.224 +
  17.225 +AMI 486 clone (1993)
  17.226 +This is a generic 486 clone with an AMI BIOS. The BIOS came from my 486SX/25, bought in December
  17.227 +1993.
  17.228 +
  17.229 +ROM files needed:
  17.230 +
  17.231 +ami1429.bin
  17.232 +
  17.233 +
  17.234 +AMI WinBIOS 486 clone (1994)
  17.235 +A 486 clone with a newer AMI BIOS.
  17.236 +
  17.237 +ROM files needed:
  17.238 +
  17.239 +ali1429g.amw
  17.240 +
  17.241 +
  17.242 +PCI 486 clone (1994)
  17.243 +A 486 clone with a PCI bus - specifically, a Shuttle HOT-433 board. Due to lack of documentation
  17.244 +this machine has some issues - in particular, don't enable the PCI IDE emulation.
  17.245 +
  17.246 +ROM files needed:
  17.247 +
  17.248 +hot-433.ami
  17.249 +
  17.250 +
  17.251 +PCem emulates the following graphics adapters :
  17.252 +
  17.253 +MDA - The original PC adapter. This displays 80x25 text in monochrome.
  17.254 +
  17.255 +Hercules - A clone of MDA, with the addition of a high-resolution 720x348 graphics mode.
  17.256 +
  17.257 +CGA - The most common of the original adapters, supporting 40x25 and 80x25 text, and 
  17.258 +    320x200 in 4 colours, 640x200 in 2 colours, and a composite mode giving 160x200 in 16 colours.
  17.259 +
  17.260 +IBM EGA - The original 1984 IBM EGA card, with 256k VRAM.
  17.261 +
  17.262 +Trident 8900D SVGA - A low cost SVGA board circa 1992/1993. Not the greatest board in it's day, but
  17.263 +    it has a reasonable VESA driver and (buggy) 15/16/24-bit colour modes.
  17.264 +
  17.265 +Tseng ET4000AX SVGA - A somewhat better SVGA board than the Trident, here you get better compatibility
  17.266 +    and speed (on the real card, not the emulator) in exchange for being limited to 8-bit colour.
  17.267 +
  17.268 +Diamond Stealth 32 SVGA - An ET4000/W32p based board, has 15/16/24-bit colour modes, plus acceleration.
  17.269 +    There is an odd bug with this one, where Windows 9x DOS boxes won't open with modes beyond 8-bit 
  17.270 +    colour. Supports PCI.
  17.271 +
  17.272 +Paradise Bahamas 64 - An S3 Vision864 based board. This has the best Windows drivers, but the default
  17.273 +    VESA driver is poor. Supports PCI.
  17.274 +
  17.275 +
  17.276 +Some models have fixed graphics adapters :
  17.277 +
  17.278 +Olivetti M24 - CGA with double-res text modes and a 640x400 mode. I haven't seen a dump of the font
  17.279 +    ROM for this yet, so if one is not provided the MDA font will be used - which looks slightly odd
  17.280 +    as it is 14-line instead of 16-line.
  17.281 +
  17.282 +Tandy 1000 - CGA with various new modes - 160x200x16, 320x200x16, 640x200x4. Widely supported in 80s 
  17.283 +    games.
  17.284 +
  17.285 +Amstrad PC1512 - CGA with a new mode (640x200x16). Only supported in GEM to my knowledge.
  17.286 +
  17.287 +Amstrad PC1640 - Paradise EGA.
  17.288 +
  17.289 +Amstrad PC2086/PC3086 - Paradise PVGA1. An early SVGA clone with 256kb VRAM.
  17.290 +
  17.291 +Amstrad MegaPC - Paradise 90C11. A development of the PVGA1, with 512kb VRAM.
  17.292 +
  17.293 +Acer 386SX/25N - Oak OTI-067. Another 512kb SVGA clone.
  17.294 +
  17.295 +
  17.296 +Pcem emulates the following sound devices :
  17.297 +
  17.298 +PC speaker - The standard beeper on all PCs. Supports samples/RealSound.
  17.299 +
  17.300 +Tandy PSG - The Texas Instruments chip in the PCjr and Tandy 1000. Supports 3 voices plus
  17.301 +    noise. I reused the emulator in B-em for this (slightly modified).
  17.302 +
  17.303 +Gameblaster - The Creative Labs Gameblaster/Creative Music System, Creative's first sound card
  17.304 +    introduced in 1987. Has two Philips SAA1099, giving 12 voices of square waves plus 4 noise
  17.305 +    voices. In stereo!
  17.306 +
  17.307 +Adlib - Has a Yamaha YM3812, giving 9 voices of 2 op FM, or 6 voices plus a useless drum section. 
  17.308 +    PCem uses Jarek Burczynski's emulator for this.
  17.309 +
  17.310 +Sound Blaster - Several Sound Blasters are emulated :
  17.311 +    SB v1.0 - The original. Limited to 22khz, and no auto-init DMA (can cause crackles sometimes).
  17.312 +    SB v1.5 - Adds auto-init DMA
  17.313 +    SB v2.0 - Upped to 41khz
  17.314 +    SB Pro v1.0 - Stereo, with twin OPL2 chips.
  17.315 +    SB Pro v2.0 - Stereo, with OPL 3 chip
  17.316 +    SB 16 - 16 bit stereo
  17.317 +    All are set to Address 220, IRQ 7 and DMA 1 (and High DMA 5). IRQ and DMA can be changed for the 
  17.318 +    SB16.
  17.319 +    The relevant SET line for autoexec.bat is
  17.320 +	SET BLASTER = A220 I7 D1 Tx    - where Tx is T1 for SB v1.0, T3 for SB v2.0, T4 for SB Pro,
  17.321 +					 and T6 for SB16.
  17.322 +    The SB16 software seems to work (including Windows drivers), but you must stick to these settings.
  17.323 +
  17.324 +Gravis Ultrasound - 32 voice sample playback. PCem's emulation of this is a bit preliminary :
  17.325 +    - Only older ULTRASND setup programs work, ie text mode instead of graphics (3.xx?)
  17.326 +    - MIDI playback occasionally goes wrong
  17.327 +    - 16-bit playback only uses top 8 bits of samples
  17.328 +    - Some games, eg later versions of Epic Pinball, have no music
  17.329 +    - No stereo
  17.330 +    - Some clicking in sound output
  17.331 +    - Does work well in lots of stuff though, eg Worms, Pinball Fantasies, Zone 66 etc.
  17.332 +    - Settings are hardwired to Address 240, IRQ 5, DMA 3. The relevant SET line for autoexec.bat is
  17.333 +	SET ULTRASND=240,3,3,5,12
  17.334 +      This means unlike on a real board, you don't have to run a init program on bootup for sound 
  17.335 +      to work. You do need to install the ULTRAMID patches if you want MIDI.
  17.336 +
  17.337 +
  17.338 +Other stuff emulated :
  17.339 +
  17.340 +Serial mouse - A Microsoft compatible serial mouse on COM1. Compatible drivers are all over the 
  17.341 +    place for this.
  17.342 +
  17.343 +M24 mouse - I haven't seen a DOS mouse driver for this yet, but the regular scancode mode works, as
  17.344 +    does the Windows 1.x driver.
  17.345 +
  17.346 +PC1512 mouse - The PC1512's perculiar quadrature mouse. You need Amstrad's actual driver for this
  17.347 +    one.
  17.348 +
  17.349 +PS/2 mouse - A PS/2 mouse is emulated on the MegaPC and 386SX/25N model. As with serial, compatible
  17.350 +    drivers are common.
  17.351 +
  17.352 +ATAPI CD-ROM - Works with OAKCDROM.SYS and Windows 9x. It can only work with actual CD-ROM drives 
  17.353 +    at the minute, so to use ISO images you need a virtual CD drive.
  17.354 +
  17.355 +
  17.356 +XTIDE :
  17.357 +
  17.358 +The XTIDE board is emulated for machines that don't natively support IDE hard discs.
  17.359 +
  17.360 +You will need to download the XTIDE BIOS seperately. Of the various versions, ide_at.bin and ide_xt.bin
  17.361 +should be placed in the ROMS directory. ide_xt is used on all XT models, and ide_at is used on the IBM AT
  17.362 +and Commodore PC30-III machines.
  17.363 +
  17.364 +The BIOS is available at :
  17.365 +
  17.366 +http://code.google.com/p/xtideuniversalbios/
  17.367 +
  17.368 +v2.0.0 beta 1 is the only version that has been tested.
  17.369 +
  17.370 +
  17.371 +Notes :
  17.372 +
  17.373 +- The AT and AMI 286 both fail part of their self test. This doesn't really affect anything, 
  17.374 +  just puts an irritating message on the screen.
  17.375 +
  17.376 +- The time on the PC1512 clock is wrong. The date is correct, though since the PC1512's bios isn't
  17.377 +  Y2k compliant, it thinks it's 1988.
  17.378 +
  17.379 +- The envelope system on the Gameblaster isn't emulated. The noise may not be right either.
  17.380 +
  17.381 +- Some of the more unusual VGA features are not emulated. I haven't found anything that uses them yet.
  17.382 +
  17.383 +- Windows 3.x should work okay in all modes now.
  17.384 +
  17.385 +- Windows 95/98 run, with the following caveats :
  17.386 +  - Mouse is not detected. Strangely, it still works - except during setup, when it stops working at one point.
  17.387 +    Sometimes running the 'Add New Hardware' wizard a couple of times will find it.
  17.388 +  - The default Trident driver only allows 16 and 256 colour modes. There is an alternative driver which enables
  17.389 +    high and true colour modes, but it doesn't work with DirectX.
  17.390 +  - Setup sometimes crashes in the first stage (during file copying). This appears to be a side effect of the 
  17.391 +    bugs fixed making OS/2 work. Unfortunately I haven't been able to eliminate this issue.
  17.392 +
  17.393 +- OS/2 1.3 seems to work okay, but I haven't tested it very thoroughly.
  17.394 +
  17.395 +- Linux appears to work. fdlinux runs okay, but is relatively useless. SuSE 6.3 seemed mostly okay, but I only
  17.396 +  had the first disc of 6 when testing, so I didn't get very far.
  17.397 +
  17.398 +- Windows NT does not work at all.
  17.399 +
  17.400 +
  17.401 +Software tested:
  17.402 +
  17.403 +I removed most of this, and only put the stuff I actually tested on this release.
  17.404 +
  17.405 +Booter games :
  17.406 +
  17.407 +King's Quest (Tandy)
  17.408 +King's Quest (CGA)
  17.409 +
  17.410 +
  17.411 +DOS stuff :
  17.412 +
  17.413 +MS-DOS 3.30
  17.414 +PC-DOS 3.30
  17.415 +PC-DOS 5.02
  17.416 +MS-DOS 6.22
  17.417 + - Most of the supplied software seems to work, eg Drivespace, Defrag, Scandisk, QBASIC
  17.418 +   etc
  17.419 +
  17.420 +OS/2 v1.3
  17.421 +
  17.422 +Windows 3.0 (CGA, Hercules, EGA, VGA) (real and standard modes only)
  17.423 +Windows 3.1 (VGA, SVGA) (standard & enhanced modes)
  17.424 +Windows 95
  17.425 +Windows 98
  17.426 +
  17.427 +Works for Windows 3.0
  17.428 +Microsoft Arcade
  17.429 +Internet Explorer 4
  17.430 +
  17.431 +Jill of the Jungle (CGA,EGA,VGA)
  17.432 +Tetris
  17.433 +Zak McKraken (CGA, Tandy)
  17.434 +
  17.435 +Brix (VGA)
  17.436 +Commander Keen 4 (EGA)
  17.437 +Duke Nukem 2 (VGA)
  17.438 +Heartlight (VGA)
  17.439 +Jetpack (VGA)
  17.440 +
  17.441 +Cascada - Cronologia (VGA)
  17.442 +EMF - Verses
  17.443 +Renaissance - Amnesia
  17.444 +Future Crew - Second Reality
  17.445 +
  17.446 +386/486 stuff :
  17.447 +
  17.448 +Jungle Strike (EMM386)
  17.449 +Dawn Patrol (EMM386) (use ET4000 driver)
  17.450 +
  17.451 +Doom
  17.452 +Doom 2
  17.453 +Duke Nukem 3D
  17.454 +Heretic
  17.455 +Hexen
  17.456 +Jazz Jackrabbit
  17.457 +Rise of the Triad
  17.458 +Simcity 2000
  17.459 +Terminal Velocity
  17.460 +Tyrian
  17.461 +Trasnport Tycoon
  17.462 +Transport Tycoon Deluxe
  17.463 +X-Com : Terror From The Deep
  17.464 +Theme Hospital - DOS and Windows versions
  17.465 +Zone 66 (don't use DOS 6.22)
  17.466 +Pro Pinball : Timeshock
  17.467 +
  17.468 +Actua Soccer
  17.469 +Grand Theft Auto
  17.470 +Jazz Jackrabbit 2
  17.471 +Magic Carpet
  17.472 +Network Q RAC Rally
  17.473 +Quake
  17.474 +WinQuake
  17.475 +Quake 2 (SLOW - unsurprisingly)
  17.476 +Tomb Raider
  17.477 +Screamer
  17.478 +Screamer Rally
  17.479 +Virtual Pool (accelerated drivers work with both S3 and ET4000/W32)
  17.480 +Jedi Knight
  17.481 +Command & Conquer : Red Alert
  17.482 +Simcity 2000
  17.483 +
  17.484 +ZSNES
  17.485 +Genecyst
  17.486 +Kgen98
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/roms/acer386/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    18.3 @@ -0,0 +1,1 @@
    18.4 +This directory needs to contain some ROM files.
    18.5 \ No newline at end of file
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/roms/ami286/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    19.3 @@ -0,0 +1,1 @@
    19.4 +This directory needs to contain some ROM files.
    19.5 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/roms/ami386/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    20.3 @@ -0,0 +1,1 @@
    20.4 +This directory needs to contain some ROM files.
    20.5 \ No newline at end of file
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/roms/ami486/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    21.3 @@ -0,0 +1,1 @@
    21.4 +This directory needs to contain some ROM files.
    21.5 \ No newline at end of file
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/roms/cmdpc30/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    22.3 @@ -0,0 +1,1 @@
    22.4 +This directory needs to contain some ROM files.
    22.5 \ No newline at end of file
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/roms/dells200/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    23.3 @@ -0,0 +1,1 @@
    23.4 +This directory needs to contain some ROM files.
    23.5 \ No newline at end of file
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/roms/dtk/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    24.3 @@ -0,0 +1,1 @@
    24.4 +This directory needs to contain some ROM files.
    24.5 \ No newline at end of file
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/roms/europc/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    25.3 @@ -0,0 +1,1 @@
    25.4 +This directory needs to contain some ROM files.
    25.5 \ No newline at end of file
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/roms/genxt/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    26.3 @@ -0,0 +1,1 @@
    26.4 +This directory needs to contain some ROM files.
    26.5 \ No newline at end of file
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/roms/hot-433/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    27.3 @@ -0,0 +1,1 @@
    27.4 +This directory needs to contain some ROM files.
    27.5 \ No newline at end of file
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/roms/ibmat/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    28.3 @@ -0,0 +1,1 @@
    28.4 +This directory needs to contain some ROM files.
    28.5 \ No newline at end of file
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/roms/ibmpc/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    29.3 @@ -0,0 +1,1 @@
    29.4 +This directory needs to contain some ROM files.
    29.5 \ No newline at end of file
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/roms/ibmxt/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    30.3 @@ -0,0 +1,1 @@
    30.4 +This directory needs to contain some ROM files.
    30.5 \ No newline at end of file
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/roms/megapc/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    31.3 @@ -0,0 +1,1 @@
    31.4 +This directory needs to contain some ROM files.
    31.5 \ No newline at end of file
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/roms/olivetti_m24/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    32.3 @@ -0,0 +1,1 @@
    32.4 +This directory needs to contain some ROM files.
    32.5 \ No newline at end of file
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/roms/pc1512/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    33.3 @@ -0,0 +1,1 @@
    33.4 +This directory needs to contain some ROM files.
    33.5 \ No newline at end of file
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/roms/pc1640/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    34.3 @@ -0,0 +1,1 @@
    34.4 +This directory needs to contain some ROM files.
    34.5 \ No newline at end of file
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/roms/pc200/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    35.3 @@ -0,0 +1,1 @@
    35.4 +This directory needs to contain some ROM files.
    35.5 \ No newline at end of file
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/roms/pc2086/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    36.3 @@ -0,0 +1,1 @@
    36.4 +This directory needs to contain some ROM files.
    36.5 \ No newline at end of file
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/roms/pc3086/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    37.3 @@ -0,0 +1,1 @@
    37.4 +This directory needs to contain some ROM files.
    37.5 \ No newline at end of file
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/roms/tandy/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    38.3 @@ -0,0 +1,1 @@
    38.4 +This directory needs to contain some ROM files.
    38.5 \ No newline at end of file
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/roms/win486/roms.txt	Sun Apr 21 14:54:35 2013 +0100
    39.3 @@ -0,0 +1,1 @@
    39.4 +This directory needs to contain some ROM files.
    39.5 \ No newline at end of file
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/src/286.c	Sun Apr 21 14:54:35 2013 +0100
    40.3 @@ -0,0 +1,3787 @@
    40.4 +#include "ibm.h"
    40.5 +#include "x86.h"
    40.6 +#include "x86_flags.h"
    40.7 +#include "cpu.h"
    40.8 +#include "pit.h"
    40.9 +#include "keyboard.h"
   40.10 +
   40.11 +#define getword getword286
   40.12 +
   40.13 +#define checkio_perm(port) if (!IOPLp) \
   40.14 +                        { \
   40.15 +                                x86gpf(NULL,0); \
   40.16 +                                break; \
   40.17 +                        }
   40.18 +
   40.19 +#undef readmemb
   40.20 +#undef writememb
   40.21 +
   40.22 +#define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)?readmemb386l(s,a):ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)])
   40.23 +#define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememb386l(s,a,v); else ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]=v
   40.24 +#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
   40.25 +
   40.26 +extern int keywaiting;
   40.27 +
   40.28 +#define checklimit(a)
   40.29 +
   40.30 +/*#define checklimit(a)   if (msw&1 && (a)) \
   40.31 +                        { \
   40.32 +                                pclog("Seg limit GPF at %04X:%04X\n",CS,pc); \
   40.33 +                                pclog("%04X %04X %04X %i %04X %04X\n", ealimitw, ealimit, eaaddr, mod, _ds.limit, _ss.limit); \
   40.34 +                                x86gpf(NULL,0); \
   40.35 +                                break; \
   40.36 +                        }*/
   40.37 +
   40.38 +#define NOTRM   if (!(msw & 1))\
   40.39 +                { \
   40.40 +                        x86_int(6); \
   40.41 +                        break; \
   40.42 +                }
   40.43 +
   40.44 +
   40.45 +static inline uint8_t geteab()
   40.46 +{
   40.47 +        if (mod==3)
   40.48 +           return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
   40.49 +//        cycles-=3;
   40.50 +        return readmemb(easeg, eaaddr);
   40.51 +}
   40.52 +
   40.53 +static inline uint16_t geteaw()
   40.54 +{
   40.55 +        if (mod==3)
   40.56 +           return regs[rm].w;
   40.57 +//        cycles-=3;
   40.58 +//        if (output==3) printf("GETEAW %04X:%08X\n",easeg,eaaddr);
   40.59 +        return readmemw(easeg, eaaddr);
   40.60 +}
   40.61 +
   40.62 +static inline uint16_t geteaw2()
   40.63 +{
   40.64 +        if (mod==3)
   40.65 +           return regs[rm].w;
   40.66 +//        cycles-=2;
   40.67 +//        printf("Getting addr from %04X:%04X %05X\n",easeg,eaaddr+2,easeg+eaaddr+2);
   40.68 +        return readmemw(easeg,(eaaddr+2)&0xFFFF);
   40.69 +}
   40.70 +
   40.71 +static inline void seteab(uint8_t val)
   40.72 +{
   40.73 +        if (mod==3)
   40.74 +        {
   40.75 +                if (rm&4) regs[rm&3].b.h=val;
   40.76 +                else      regs[rm&3].b.l=val;
   40.77 +        }
   40.78 +        else
   40.79 +        {
   40.80 +//                cycles-=2;
   40.81 +                writememb(easeg, eaaddr, val);
   40.82 +        }
   40.83 +}
   40.84 +
   40.85 +static inline void seteaw(uint16_t val)
   40.86 +{
   40.87 +        if (mod==3)
   40.88 +           regs[rm].w=val;
   40.89 +        else
   40.90 +        {
   40.91 +//                cycles-=2;
   40.92 +                writememw(easeg, eaaddr, val);
   40.93 +//                writememb(easeg+eaaddr+1,val>>8);
   40.94 +        }
   40.95 +}
   40.96 +
   40.97 +#undef fetchea
   40.98 +
   40.99 +#define fetchea()   { rmdat=readmemb(cs, pc); pc++;     \
  40.100 +                    reg=(rmdat>>3)&7;                  \
  40.101 +                    mod=(rmdat>>6)&3;                  \
  40.102 +                    rm=rmdat&7;                        \
  40.103 +                    if (mod!=3) fetcheal286(); }
  40.104 +
  40.105 +void fetcheal286()
  40.106 +{
  40.107 +        if (!mod && rm==6) { eaaddr=getword(); easeg=ds; ealimit=_ds.limit; ealimitw=_ds.limitw; }
  40.108 +        else
  40.109 +        {
  40.110 +                switch (mod)
  40.111 +                {
  40.112 +                        case 0:
  40.113 +                        eaaddr=0;
  40.114 +                        break;
  40.115 +                        case 1:
  40.116 +                        eaaddr=(uint16_t)(int8_t)readmemb(cs, pc); pc++;
  40.117 +                        break;
  40.118 +                        case 2:
  40.119 +                        eaaddr=getword();
  40.120 +                        break;
  40.121 +                }
  40.122 +                eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]);
  40.123 +                easeg=*mod1seg[rm];
  40.124 +                if (mod1seg[rm] == &ss) { ealimit=_ss.limit; ealimitw=_ss.limitw; }
  40.125 +                else                    { ealimit=_ds.limit; ealimitw=_ds.limitw; }
  40.126 +//                if (output) pclog("Limit %08X %08X %08X %08X\n",ealimit,_ds.limit,mod1seg[rm],&ss);
  40.127 +        }
  40.128 +        eaaddr&=0xFFFF;        
  40.129 +}
  40.130 +
  40.131 +void rep286(int fv)
  40.132 +{
  40.133 +        uint8_t temp;
  40.134 +        uint32_t c;//=CX;
  40.135 +        uint8_t temp2;
  40.136 +        uint16_t tempw,tempw2,tempw3,of=flags;
  40.137 +        uint32_t ipc=oldpc;//pc-1;
  40.138 +        int changeds=0;
  40.139 +        uint32_t oldds;
  40.140 +        uint32_t templ,templ2;
  40.141 +        int tempz;
  40.142 +        int tempi;
  40.143 +//        if (output) pclog("REP32 %04X %04X  ",use32,rep32);
  40.144 +        startrep:
  40.145 +        temp=opcode2=readmemb(cs,pc); pc++;
  40.146 +//        if (firstrepcycle && temp==0xA5) pclog("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
  40.147 +//        if (output) pclog("REP %02X %04X\n",temp,ipc);
  40.148 +        c = CX;
  40.149 +/*        if (rep32 && (msw&1))
  40.150 +        {
  40.151 +                if (temp!=0x67 && temp!=0x66 && (rep32|temp)!=0x1AB && (rep32|temp)!=0x3AB) pclog("32-bit REP %03X %08X %04X:%06X\n",temp|rep32,c,CS,pc);
  40.152 +        }*/
  40.153 +        switch (temp)
  40.154 +        {
  40.155 +                case 0x26: /*ES:*/
  40.156 +                oldds=ds;
  40.157 +                ds=es;
  40.158 +                rds=ES;
  40.159 +                changeds=1;
  40.160 +                goto startrep;
  40.161 +                break;
  40.162 +                case 0x2E: /*CS:*/
  40.163 +                oldds=ds;
  40.164 +                ds=cs;
  40.165 +                rds=CS;
  40.166 +                changeds=1;
  40.167 +                goto startrep;
  40.168 +                break;
  40.169 +                case 0x36: /*SS:*/
  40.170 +                oldds=ds;
  40.171 +                ds=ss;
  40.172 +                rds=SS;
  40.173 +                changeds=1;
  40.174 +                goto startrep;
  40.175 +                break;
  40.176 +                case 0x3E: /*DS:*/
  40.177 +                oldds=ds;
  40.178 +                ds=ds;
  40.179 +                changeds=1;
  40.180 +                goto startrep;
  40.181 +                break;
  40.182 +                case 0x6C: /*REP INSB*/
  40.183 +                if (c>0)
  40.184 +                {
  40.185 +                        checkio_perm(DX);
  40.186 +                        temp2=inb(DX);
  40.187 +                        writememb(es,DI,temp2);
  40.188 +                        if (abrt) break;
  40.189 +                        if (flags&D_FLAG) DI--;
  40.190 +                        else              DI++;
  40.191 +                        c--;
  40.192 +                        cycles-=15;
  40.193 +                }
  40.194 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.195 +                else firstrepcycle=1;
  40.196 +                break;
  40.197 +                case 0x6D: /*REP INSW*/
  40.198 +                if (c>0)
  40.199 +                {
  40.200 +                        tempw=inw(DX);
  40.201 +                        writememw(es,DI,tempw);
  40.202 +                        if (abrt) break;
  40.203 +                        if (flags&D_FLAG) DI-=2;
  40.204 +                        else              DI+=2;
  40.205 +                        c--;
  40.206 +                        cycles-=15;
  40.207 +                }
  40.208 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.209 +                else firstrepcycle=1;
  40.210 +                break;
  40.211 +                case 0x6E: /*REP OUTSB*/
  40.212 +                if (c>0)
  40.213 +                {
  40.214 +                        temp2=readmemb(ds,SI);
  40.215 +                        if (abrt) break;
  40.216 +                        checkio_perm(DX);
  40.217 +                        outb(DX,temp2);
  40.218 +                        if (flags&D_FLAG) SI--;
  40.219 +                        else              SI++;
  40.220 +                        c--;
  40.221 +                        cycles-=14;
  40.222 +                }
  40.223 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.224 +                else firstrepcycle=1;
  40.225 +                break;
  40.226 +                case 0x6F: /*REP OUTSW*/
  40.227 +                if (c>0)
  40.228 +                {
  40.229 +                        tempw=readmemw(ds,SI);
  40.230 +                        if (abrt) break;
  40.231 +//                        pclog("OUTSW %04X -> %04X\n",SI,tempw);
  40.232 +                        outw(DX,tempw);
  40.233 +                        if (flags&D_FLAG) SI-=2;
  40.234 +                        else              SI+=2;
  40.235 +                        c--;
  40.236 +                        cycles-=14;
  40.237 +                }
  40.238 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.239 +                else firstrepcycle=1;
  40.240 +                break;
  40.241 +                case 0xA4: /*REP MOVSB*/
  40.242 +                if (c>0)
  40.243 +                {
  40.244 +                        temp2=readmemb(ds,SI);  if (abrt) break;
  40.245 +                        writememb(es,DI,temp2); if (abrt) break;
  40.246 +//                        if (output==3) pclog("MOVSB %08X:%04X -> %08X:%04X %02X\n",ds,SI,es,DI,temp2);
  40.247 +                        if (flags&D_FLAG) { DI--; SI--; }
  40.248 +                        else              { DI++; SI++; }
  40.249 +                        c--;
  40.250 +                        cycles-=(is486)?3:4;
  40.251 +                }
  40.252 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.253 +                else firstrepcycle=1;
  40.254 +                break;
  40.255 +                case 0xA5: /*REP MOVSW*/
  40.256 +                if (c>0)
  40.257 +                {
  40.258 +                        tempw=readmemw(ds,SI);  if (abrt) break;
  40.259 +                        writememw(es,DI,tempw); if (abrt) break;
  40.260 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
  40.261 +                        else              { DI+=2; SI+=2; }
  40.262 +                        c--;
  40.263 +                        cycles-=(is486)?3:4;
  40.264 +                }
  40.265 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.266 +                else firstrepcycle=1;
  40.267 +                break;
  40.268 +                case 0xA6: /*REP CMPSB*/
  40.269 +                if (fv) flags|=Z_FLAG;
  40.270 +                else    flags&=~Z_FLAG;
  40.271 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  40.272 +                {
  40.273 +                        temp=readmemb(ds,SI);
  40.274 +                        temp2=readmemb(es,DI);
  40.275 +                        if (abrt) { flags=of; break; }
  40.276 +                        if (flags&D_FLAG) { DI--; SI--; }
  40.277 +                        else              { DI++; SI++; }
  40.278 +                        c--;
  40.279 +                        cycles-=(is486)?7:9;
  40.280 +                        setsub8(temp,temp2);
  40.281 +                }
  40.282 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  40.283 +                else firstrepcycle=1;
  40.284 +                break;
  40.285 +                case 0xA7: /*REP CMPSW*/
  40.286 +                if (fv) flags|=Z_FLAG;
  40.287 +                else    flags&=~Z_FLAG;
  40.288 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  40.289 +                {
  40.290 +                        tempw=readmemw(ds,SI);
  40.291 +                        tempw2=readmemw(es,DI);
  40.292 +                        if (abrt) { flags=of; break; }
  40.293 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
  40.294 +                        else              { DI+=2; SI+=2; }
  40.295 +                        c--;
  40.296 +                        cycles-=(is486)?7:9;
  40.297 +                        setsub16(tempw,tempw2);
  40.298 +                }
  40.299 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  40.300 +                else firstrepcycle=1;
  40.301 +                break;
  40.302 +
  40.303 +                case 0xAA: /*REP STOSB*/
  40.304 +                if (c>0)
  40.305 +                {
  40.306 +                        writememb(es,DI,AL);
  40.307 +                        if (abrt) break;
  40.308 +                        if (flags&D_FLAG) DI--;
  40.309 +                        else              DI++;
  40.310 +                        c--;
  40.311 +                        cycles-=(is486)?4:5;
  40.312 +                }
  40.313 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.314 +                else firstrepcycle=1;
  40.315 +                break;
  40.316 +                case 0xAB: /*REP STOSW*/
  40.317 +                if (c>0)
  40.318 +                {
  40.319 +                        writememw(es,DI,AX);
  40.320 +                        if (abrt) break;
  40.321 +                        if (flags&D_FLAG) DI-=2;
  40.322 +                        else              DI+=2;
  40.323 +                        c--;
  40.324 +                        cycles-=(is486)?4:5;
  40.325 +                }
  40.326 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.327 +                else firstrepcycle=1;
  40.328 +                break;
  40.329 +                case 0xAC: /*REP LODSB*/
  40.330 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
  40.331 +                if (c>0)
  40.332 +                {
  40.333 +                        AL=readmemb(ds,SI);
  40.334 +                        if (abrt) break;
  40.335 +                        if (flags&D_FLAG) SI--;
  40.336 +                        else              SI++;
  40.337 +                        c--;
  40.338 +                        cycles-=5;
  40.339 +                }
  40.340 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.341 +                else firstrepcycle=1;
  40.342 +                break;
  40.343 +                case 0xAD: /*REP LODSW*/
  40.344 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
  40.345 +                if (c>0)
  40.346 +                {
  40.347 +                        AX=readmemw(ds,SI);
  40.348 +                        if (abrt) break;
  40.349 +                        if (flags&D_FLAG) SI-=2;
  40.350 +                        else              SI+=2;
  40.351 +                        c--;
  40.352 +                        cycles-=5;
  40.353 +                }
  40.354 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  40.355 +                else firstrepcycle=1;
  40.356 +                break;
  40.357 +                case 0xAE: /*REP SCASB*/
  40.358 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc);
  40.359 +//                tempz=(fv)?1:0;
  40.360 +                if (fv) flags|=Z_FLAG;
  40.361 +                else    flags&=~Z_FLAG;
  40.362 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  40.363 +                {
  40.364 +                        temp2=readmemb(es,DI);
  40.365 +                        if (abrt) { flags=of; break; }
  40.366 +                        setsub8(AL,temp2);
  40.367 +                        if (flags&D_FLAG) DI--;
  40.368 +                        else              DI++;
  40.369 +                        c--;
  40.370 +                        cycles-=(is486)?5:8;
  40.371 +                }
  40.372 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  40.373 +                else firstrepcycle=1;
  40.374 +                break;
  40.375 +                case 0xAF: /*REP SCASW*/
  40.376 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc);
  40.377 +                if (fv) flags|=Z_FLAG;
  40.378 +                else    flags&=~Z_FLAG;
  40.379 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  40.380 +                {
  40.381 +                        tempw=readmemw(es,DI);
  40.382 +                        if (abrt) { flags=of; break; }
  40.383 +                        setsub16(AX,tempw);
  40.384 +                        if (flags&D_FLAG) DI-=2;
  40.385 +                        else              DI+=2;
  40.386 +                        c--;
  40.387 +                        cycles-=(is486)?5:8;
  40.388 +                }
  40.389 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  40.390 +                else firstrepcycle=1;
  40.391 +                break;
  40.392 +
  40.393 +                default:
  40.394 +                        pc=ipc;
  40.395 +                        cycles-=20;
  40.396 +                x86illegal();
  40.397 +                pclog("Bad REP %02X\n", temp);
  40.398 +                //dumpregs();
  40.399 +                //exit(-1);
  40.400 +        }
  40.401 +        CX=c;
  40.402 +        if (changeds) ds=oldds;
  40.403 +//        if (output) pclog("%03X %03X\n",rep32,use32);
  40.404 +}
  40.405 +
  40.406 +void x86illegal()
  40.407 +{
  40.408 +        uint16_t addr;
  40.409 +        pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
  40.410 +//        if (output)
  40.411 +//        {
  40.412 +//                dumpregs();
  40.413 +//                exit(-1);
  40.414 +//        }
  40.415 +        if (msw&1)
  40.416 +        {
  40.417 +                pmodeint(6,0);
  40.418 +        }
  40.419 +        else
  40.420 +        {
  40.421 +                if (ssegs) { ss=oldss; _ss.limit=oldsslimit; _ss.limitw=oldsslimitw; }
  40.422 +                writememw(ss,((SP-2)&0xFFFF),flags);
  40.423 +                writememw(ss,((SP-4)&0xFFFF),CS);
  40.424 +                writememw(ss,((SP-6)&0xFFFF),pc);
  40.425 +                SP-=6;
  40.426 +                flags&=~I_FLAG;
  40.427 +                flags&=~T_FLAG;
  40.428 +                addr=6<<2;
  40.429 +                pc=readmemw(0,addr);
  40.430 +                loadcs(readmemw(0,addr+2));
  40.431 +        }
  40.432 +        cycles-=70;
  40.433 +}
  40.434 +//#endif
  40.435 +//#if 0
  40.436 +
  40.437 +static inline uint8_t getbytef()
  40.438 +{
  40.439 +        uint8_t temp = readmemb(cs, pc); pc++;
  40.440 +        return temp;
  40.441 +}
  40.442 +static inline uint16_t getwordf()
  40.443 +{
  40.444 +        uint16_t tempw = readmemw(cs, pc); pc+=2;
  40.445 +        return tempw;
  40.446 +}
  40.447 +
  40.448 +/*Conditional jump timing is WRONG*/
  40.449 +void exec286(int cycs)
  40.450 +{
  40.451 +        uint8_t temp,temp2;
  40.452 +        uint16_t addr,tempw,tempw2,tempw3,tempw4;
  40.453 +        int8_t offset;
  40.454 +        volatile int tempws, tempws2;
  40.455 +        uint32_t templ, templ2, templ3;
  40.456 +        int8_t temps;
  40.457 +        int16_t temps16;
  40.458 +        int c;//,cycdiff;
  40.459 +        int tempi;
  40.460 +        FILE *f;
  40.461 +        int trap;
  40.462 +        int cyclast;
  40.463 +//        printf("Run 286! %i %i\n",cycles,cycs);
  40.464 +        cycles+=cycs;
  40.465 +//        i86_Execute(cycs);
  40.466 +//        return;
  40.467 +        while (cycles>0)
  40.468 +        {
  40.469 +                cyclast = cycdiff;
  40.470 +                cycdiff=cycles;
  40.471 +                oldcs=CS;
  40.472 +                oldpc=pc;
  40.473 +                oldcpl=CPL;
  40.474 +                
  40.475 +                opcodestart:
  40.476 +                opcode = readmemb(cs, pc);
  40.477 +                if (abrt) goto opcodeend;
  40.478 +                tempc=flags&C_FLAG;
  40.479 +                trap=flags&T_FLAG;
  40.480 +                
  40.481 +                if (output && /*cs<0xF0000 && */!ssegs)//opcode!=0x26 && opcode!=0x36 && opcode!=0x2E && opcode!=0x3E)
  40.482 +                {
  40.483 +                        if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
  40.484 +                        {
  40.485 +                                if (!skipnextprint) printf("%04X(%06X):%04X : %04X %04X %04X %04X %04X(%06X) %04X(%06X) %04X(%06X) %04X(%06X) %04X %04X %04X %04X %02X %04X  %04X  %04X %04X %04X  %08X %i %i  %i %08X  %i %f %f\n",CS,cs,pc,AX,BX,CX,DX,CS,cs,DS,ds,ES,es,SS,ss,DI,SI,BP,SP,opcode,flags,msw,ram[0x7c3e],ram[(0x7c3e)+3],ram[0x7c40],_ds.limitw,keybsenddelay,keywaiting,ins, _ss.limit, cyclast, pit.c[1], PITCONST);
  40.486 +                                skipnextprint=0;
  40.487 +//                                ins++;
  40.488 +/*                                if (ins==50000)
  40.489 +                                {
  40.490 +                                        dumpregs();
  40.491 +                                        exit(-1);
  40.492 +                                }*/
  40.493 +/*                                if (ins==500000)
  40.494 +                                {
  40.495 +                                        dumpregs();
  40.496 +                                        exit(-1);
  40.497 +                                }*/
  40.498 +                        }
  40.499 +                }
  40.500 +//#endif
  40.501 +                pc++;
  40.502 +                inhlt=0;
  40.503 +//                if (ins==500000) { dumpregs(); exit(0); }*/
  40.504 +                switch (opcode)
  40.505 +                {
  40.506 +                        case 0x00: /*ADD 8,reg*/
  40.507 +                        fetchea();
  40.508 +                        //if (!rmdat && output) pc--;
  40.509 +/*                        if (!rmdat && output)
  40.510 +                        {
  40.511 +                                pclog("Crashed\n");
  40.512 +//                                clear_keybuf();
  40.513 +//                                readkey();
  40.514 +                                dumpregs();
  40.515 +                                exit(-1);
  40.516 +                        }*/
  40.517 +                        if (mod == 3)
  40.518 +                        {
  40.519 +                                temp  = getr8(rm);
  40.520 +                                temp2 = getr8(reg);
  40.521 +                                setadd8(temp, temp2);
  40.522 +                                setr8(rm, temp + temp2);
  40.523 +                                cycles -= 2;
  40.524 +                        }
  40.525 +                        else
  40.526 +                        {
  40.527 +                                temp  = geteab();     if (abrt) break;
  40.528 +                                temp2 = getr8(reg);
  40.529 +                                seteab(temp + temp2); if (abrt) break;
  40.530 +                                setadd8(temp, temp2);
  40.531 +                                cycles -= 7;
  40.532 +                        }
  40.533 +                        break;
  40.534 +                        case 0x01: /*ADD 16,reg*/
  40.535 +                        fetchea();
  40.536 +                        if (mod == 3)
  40.537 +                        {
  40.538 +                                setadd16(regs[rm].w, regs[reg].w);
  40.539 +                                regs[rm].w += regs[reg].w;
  40.540 +                                cycles -= 2;
  40.541 +                        }
  40.542 +                        else
  40.543 +                        {
  40.544 +                                tempw = geteaw();             if (abrt) break;
  40.545 +                                seteaw(tempw + regs[reg].w);  if (abrt) break;
  40.546 +                                setadd16(tempw, regs[reg].w);
  40.547 +                                cycles -= 7;
  40.548 +                        }
  40.549 +                        break;
  40.550 +                        case 0x02: /*ADD reg,8*/
  40.551 +                        fetchea();
  40.552 +                        temp=geteab();        if (abrt) break;
  40.553 +                        setadd8(getr8(reg),temp);
  40.554 +                        setr8(reg,getr8(reg)+temp);
  40.555 +                        cycles -= (mod == 3) ? 2 : 7;
  40.556 +                        break;
  40.557 +                        case 0x03: /*ADD reg,16*/
  40.558 +                        fetchea();
  40.559 +                        tempw=geteaw();       if (abrt) break;
  40.560 +                        setadd16(regs[reg].w,tempw);
  40.561 +                        regs[reg].w+=tempw;
  40.562 +                        cycles -= (mod == 3) ? 2 : 7;
  40.563 +                        break;
  40.564 +                        case 0x04: /*ADD AL,#8*/
  40.565 +                        temp=getbytef();
  40.566 +                        setadd8(AL,temp);
  40.567 +                        AL+=temp;
  40.568 +                        cycles -= 3;
  40.569 +                        break;
  40.570 +                        case 0x05: /*ADD AX,#16*/
  40.571 +                        tempw=getwordf();
  40.572 +                        setadd16(AX,tempw);
  40.573 +                        AX+=tempw;
  40.574 +                        cycles -= 3;
  40.575 +                        break;
  40.576 +
  40.577 +                        case 0x06: /*PUSH ES*/
  40.578 +                        if (ssegs) ss=oldss;
  40.579 +                        writememw(ss,((SP-2)&0xFFFF),ES); if (abrt) break;
  40.580 +                        SP-=2;
  40.581 +                        cycles-=3;
  40.582 +                        break;
  40.583 +                        case 0x07: 
  40.584 +                        if (ssegs) ss=oldss;
  40.585 +                        tempw=readmemw(ss,SP);          if (abrt) break;
  40.586 +                        loadseg(tempw,&_es);            if (abrt) break;
  40.587 +                        SP+=2;
  40.588 +                        cycles -= (msw & 1) ? 20 : 5;
  40.589 +                        break;
  40.590 +
  40.591 +                        case 0x08: /*OR 8,reg*/
  40.592 +                        fetchea();
  40.593 +                        if (mod == 3)
  40.594 +                        {
  40.595 +                                temp  = getr8(rm) | getr8(reg);
  40.596 +                                setr8(rm, temp);
  40.597 +                                setznp8(temp);
  40.598 +                                cycles -= 2;
  40.599 +                        }
  40.600 +                        else
  40.601 +                        {
  40.602 +                                temp  = geteab();          if (abrt) break;
  40.603 +                                temp2 = getr8(reg);
  40.604 +                                seteab(temp | temp2);     if (abrt) break;
  40.605 +                                setznp8(temp | temp2);
  40.606 +                                cycles -= 7;
  40.607 +                        }
  40.608 +                        break;
  40.609 +                        case 0x09: /*OR 16,reg*/
  40.610 +                        fetchea();
  40.611 +                        if (mod == 3)
  40.612 +                        {
  40.613 +                                regs[rm].w |= regs[reg].w;
  40.614 +                                setznp16(regs[rm].w);
  40.615 +                                cycles -= 2;
  40.616 +                        }
  40.617 +                        else
  40.618 +                        {
  40.619 +                                tempw = geteaw() | regs[reg].w; if (abrt) break;
  40.620 +                                seteaw(tempw);                  if (abrt) break;
  40.621 +                                setznp16(tempw);
  40.622 +                                cycles -= 7;
  40.623 +                        }
  40.624 +                        break;
  40.625 +                        case 0x0A: /*OR reg,8*/
  40.626 +                        fetchea();
  40.627 +                        temp=geteab();          if (abrt) break;
  40.628 +                        temp|=getr8(reg);
  40.629 +                        setznp8(temp);
  40.630 +                        setr8(reg,temp);
  40.631 +                        cycles -= (mod == 3) ? 2 : 7;
  40.632 +                        break;
  40.633 +                        case 0x0B: /*OR reg,16*/
  40.634 +                        fetchea();
  40.635 +                        tempw=geteaw();         if (abrt) break;
  40.636 +                        tempw|=regs[reg].w;
  40.637 +                        setznp16(tempw);
  40.638 +                        regs[reg].w=tempw;
  40.639 +                        cycles -= (mod == 3) ? 2 : 7;
  40.640 +                        break;
  40.641 +                        case 0x0C: /*OR AL,#8*/
  40.642 +                        AL|=getbytef();
  40.643 +                        setznp8(AL);
  40.644 +                        cycles -= 2;
  40.645 +                        break;
  40.646 +                        case 0x0D: /*OR AX,#16*/
  40.647 +                        AX|=getwordf();
  40.648 +                        setznp16(AX);
  40.649 +                        cycles -= 2;
  40.650 +                        break;
  40.651 +
  40.652 +                        case 0x0E: /*PUSH CS*/
  40.653 +                        if (ssegs) ss=oldss;
  40.654 +                        writememw(ss,((SP-2)&0xFFFF),CS);       if (abrt) break;
  40.655 +                        SP-=2;
  40.656 +                        cycles-=3;
  40.657 +                        break;
  40.658 +
  40.659 +                        case 0x0F:
  40.660 +                        temp = readmemb(cs, pc); pc++;
  40.661 +                        opcode2 = temp;
  40.662 +//                        if (temp>5 && temp!=0x82 && temp!=0x85 && temp!=0x84 && temp!=0x87 && temp!=0x8D && temp!=0x8F && temp!=0x8C && temp!=0x20 && temp!=0x22) pclog("Using magic 386 0F instruction %02X!\n",temp);
  40.663 +                        switch (temp)
  40.664 +                        {
  40.665 +                                case 0:
  40.666 +                                fetchea(); if (abrt) break;
  40.667 +                                switch (rmdat&0x38)
  40.668 +                                {
  40.669 +                                        case 0x00: /*SLDT*/
  40.670 +                                        NOTRM
  40.671 +                                        seteaw(ldt.seg);
  40.672 +                                        cycles -= (mod == 3) ? 3 : 2;
  40.673 +                                        break;
  40.674 +                                        case 0x08: /*STR*/
  40.675 +                                        NOTRM
  40.676 +                                        seteaw(tr.seg);
  40.677 +                                        cycles -= (mod == 3) ? 3 : 2;
  40.678 +                                        break;
  40.679 +                                        case 0x10: /*LLDT*/
  40.680 +                                        if (CPL && (msw & 1))
  40.681 +                                        {
  40.682 +                                                pclog("Invalid LLDT!\n");
  40.683 +                                                x86gpf(NULL,0);
  40.684 +                                                break;
  40.685 +                                        }
  40.686 +                                        NOTRM
  40.687 +                                        ldt.seg=geteaw();
  40.688 +//                                        pclog("Load LDT %04X ",ldt.seg);
  40.689 +                                        templ=(ldt.seg&~7)+gdt.base;
  40.690 +//                                        pclog("%06X ",gdt.base);
  40.691 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
  40.692 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
  40.693 +                                        if (abrt) break;
  40.694 +                                        ldt.limit=templ3;
  40.695 +                                        ldt.access=readmemb(0,templ+6);
  40.696 +                                        if (readmemb(0,templ+6)&0x80)
  40.697 +                                        {
  40.698 +                                                ldt.limit<<=12;
  40.699 +                                                ldt.limit|=0xFFF;
  40.700 +                                        }
  40.701 +                                        ldt.base=templ2;
  40.702 +//                                        /*if (output==3) */pclog("LLDT %04X %08X %04X  %08X %08X\n",ldt.seg,ldt.base,ldt.limit,readmeml(0,templ),readmeml(0,templ+4));
  40.703 +
  40.704 +                                        cycles -= (mod == 3) ? 17 : 19;
  40.705 +                                        break;
  40.706 +                                        case 0x18: /*LTR*/
  40.707 +                                        if (CPL && (msw & 1))
  40.708 +                                        {
  40.709 +                                                pclog("Invalid LTR!\n");
  40.710 +                                                x86gpf(NULL,0);
  40.711 +                                                break;
  40.712 +                                        }
  40.713 +                                        NOTRM
  40.714 +                                        tr.seg=geteaw();
  40.715 +                                        templ=(tr.seg&~7)+gdt.base;
  40.716 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
  40.717 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
  40.718 +                                        temp=readmemb(0,templ+5);
  40.719 +                                        if (abrt) break;
  40.720 +                                        tr.limit=templ3;
  40.721 +                                        tr.access=readmemb(0,templ+6);
  40.722 +                                        if (readmemb(0,templ+6)&0x80)
  40.723 +                                        {
  40.724 +                                                tr.limit<<=12;
  40.725 +                                                tr.limit|=0xFFF;
  40.726 +                                        }
  40.727 +                                        tr.base=templ2;
  40.728 +//                                        pclog("TR base = %08X\n",templ2);
  40.729 +                                        tr.access=temp;
  40.730 +                                        cycles -= (mod == 3) ? 17 : 19;
  40.731 +                                        break;
  40.732 +                                        case 0x20: /*VERR*/
  40.733 +                                        NOTRM
  40.734 +                                        tempw=geteaw(); if (abrt) break;
  40.735 +                                        flags&=~Z_FLAG;
  40.736 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
  40.737 +                                        cpl_override=1;
  40.738 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
  40.739 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
  40.740 +                                        cpl_override=0;
  40.741 +                                        if (abrt) break;
  40.742 +                                        if (!(tempw2&0x1000)) tempi=0;
  40.743 +                                        if ((tempw2&0xC00)!=0xC00) /*Exclude conforming code segments*/
  40.744 +                                        {
  40.745 +                                                tempw3=(tempw2>>13)&3; /*Check permissions*/
  40.746 +                                                if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
  40.747 +                                        }
  40.748 +                                        if ((tempw2&0x0800) && !(tempw2&0x0200)) tempi=0; /*Non-readable code*/
  40.749 +                                        if (tempi) flags|=Z_FLAG;
  40.750 +                                        cycles -= (mod == 3) ? 14 : 16;
  40.751 +                                        break;
  40.752 +                                        case 0x28: /*VERW*/
  40.753 +                                        NOTRM
  40.754 +                                        tempw=geteaw(); if (abrt) break;
  40.755 +                                        flags&=~Z_FLAG;
  40.756 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
  40.757 +                                        cpl_override=1;
  40.758 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
  40.759 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
  40.760 +                                        cpl_override=0;
  40.761 +                                        if (abrt) break;
  40.762 +                                        if (!(tempw2&0x1000)) tempi=0;
  40.763 +                                        tempw3=(tempw2>>13)&3; /*Check permissions*/
  40.764 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
  40.765 +                                        if (tempw2&0x0800) tempi=0; /*Code*/
  40.766 +                                        else if (!(tempw2&0x0200)) tempi=0; /*Read-only data*/
  40.767 +                                        if (tempi) flags|=Z_FLAG;
  40.768 +                                        cycles -= (mod == 3) ? 14 : 16;
  40.769 +                                        break;
  40.770 +
  40.771 +
  40.772 +                                        default:
  40.773 +                                        pclog("Bad 0F 00 opcode %02X\n",rmdat&0x38);
  40.774 +                                        pc-=3;
  40.775 +                                        x86illegal();
  40.776 +                                        break;
  40.777 +//                                        dumpregs();
  40.778 +//                                        exit(-1);
  40.779 +                                }
  40.780 +                                break;
  40.781 +                                case 1:
  40.782 +                                fetchea(); if (abrt) break;
  40.783 +                                switch (rmdat&0x38)
  40.784 +                                {
  40.785 +                                        case 0x00: /*SGDT*/
  40.786 +                                        seteaw(gdt.limit);
  40.787 +                                        writememw(easeg, eaaddr + 2, gdt.base);
  40.788 +                                        writememw(easeg, eaaddr + 4, (gdt.base >> 16) | 0xFF00);
  40.789 +                                        cycles -= 11;
  40.790 +                                        break;
  40.791 +                                        case 0x08: /*SIDT*/
  40.792 +                                        seteaw(idt.limit);
  40.793 +                                        writememw(easeg, eaaddr + 2, idt.base);
  40.794 +                                        writememw(easeg, eaaddr + 4, (idt.base >> 16) | 0xFF00);
  40.795 +                                        cycles -= 12;
  40.796 +                                        break;
  40.797 +                                        case 0x10: /*LGDT*/
  40.798 +                                        if (CPL && (msw & 1))
  40.799 +                                        {
  40.800 +                                                pclog("Invalid LGDT!\n");
  40.801 +                                                x86gpf(NULL,0);
  40.802 +                                                break;
  40.803 +                                        }
  40.804 +                                        tempw=geteaw();
  40.805 +                                        templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF;
  40.806 +                                        if (abrt) break;
  40.807 +                                        gdt.limit=tempw;
  40.808 +                                        gdt.base=templ;
  40.809 +                                        cycles-=11;
  40.810 +                                        break;
  40.811 +                                        case 0x18: /*LIDT*/
  40.812 +                                        if (CPL && (msw & 1))
  40.813 +                                        {
  40.814 +                                                pclog("Invalid LIDT!\n");
  40.815 +                                                x86gpf(NULL,0);
  40.816 +                                                break;
  40.817 +                                        }
  40.818 +                                        tempw=geteaw();
  40.819 +                                        templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF;
  40.820 +                                        if (abrt) break;
  40.821 +                                        idt.limit=tempw;
  40.822 +                                        idt.base=templ;
  40.823 +                                        cycles-=12;
  40.824 +                                        break;
  40.825 +
  40.826 +                                        case 0x20: /*SMSW*/
  40.827 +                                        if (is486) seteaw(msw);
  40.828 +                                        else       seteaw(msw|0xFF00);
  40.829 +//                                        pclog("SMSW %04X:%04X  %04X %i\n",CS,pc,msw,is486);
  40.830 +                                        cycles -= (mod == 3) ? 2 : 3;
  40.831 +                                        break;
  40.832 +                                        case 0x30: /*LMSW*/
  40.833 +                                        if (CPL && (msw&1))
  40.834 +                                        {
  40.835 +                                                pclog("LMSW - ring not zero!\n");
  40.836 +                                                x86gpf(NULL,0);
  40.837 +                                                break;
  40.838 +                                        }
  40.839 +                                        tempw=geteaw(); if (abrt) break;
  40.840 +                                        if (msw&1) tempw|=1;
  40.841 +                                        msw=tempw;
  40.842 +                                        cycles -= (mod == 3) ? 3 : 6;
  40.843 +                                        pclog("LMSW %04X %08X %04X:%04X\n", msw, cs, CS, pc);
  40.844 +                                        break;
  40.845 +
  40.846 +                                        default:
  40.847 +                                        pclog("Bad 0F 01 opcode %02X\n",rmdat&0x38);
  40.848 +                                        pc-=3;
  40.849 +                                        x86illegal();
  40.850 +                                        break;
  40.851 +//                                        dumpregs();
  40.852 +//                                        exit(-1);
  40.853 +                                }
  40.854 +                                break;
  40.855 +
  40.856 +                                case 2: /*LAR*/
  40.857 +                                NOTRM
  40.858 +                                fetchea();
  40.859 +                                tempw=geteaw(); if (abrt) break;
  40.860 +//                                pclog("LAR seg %04X\n",tempw);
  40.861 +                                
  40.862 +                                if (!(tempw&0xFFFC)) { flags&=~Z_FLAG; break; } /*Null selector*/
  40.863 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
  40.864 +                                if (tempi)
  40.865 +                                {
  40.866 +                                        cpl_override=1;
  40.867 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
  40.868 +                                        cpl_override=0;
  40.869 +                                        if (abrt) break;
  40.870 +                                }
  40.871 +                                flags&=~Z_FLAG;
  40.872 +//                                pclog("tempw2 %04X  %i  %04X %04X\n",tempw2,tempi,ldt.limit,gdt.limit);
  40.873 +                                if ((tempw2&0x1F00)==0x000) tempi=0;
  40.874 +                                if ((tempw2&0x1F00)==0x800) tempi=0;
  40.875 +                                if ((tempw2&0x1F00)==0xA00) tempi=0;
  40.876 +                                if ((tempw2&0x1F00)==0xD00) tempi=0;
  40.877 +                                if ((tempw2&0x1C00)<0x1C00) /*Exclude conforming code segments*/
  40.878 +                                {
  40.879 +                                        tempw3=(tempw2>>13)&3;
  40.880 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
  40.881 +                                }
  40.882 +                                if (tempi)
  40.883 +                                {
  40.884 +                                        flags|=Z_FLAG;
  40.885 +                                        cpl_override=1;
  40.886 +                                        regs[reg].w=readmemb(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+5)<<8;
  40.887 +                                        cpl_override=0;
  40.888 +                                }
  40.889 +                                cycles -= (mod == 3) ? 14 : 16;
  40.890 +                                break;
  40.891 +
  40.892 +                                case 3: /*LSL*/
  40.893 +                                NOTRM
  40.894 +                                fetchea();
  40.895 +                                tempw=geteaw(); if (abrt) break;
  40.896 +                                flags&=~Z_FLAG;
  40.897 +                                if (!(tempw&0xFFFC)) break; /*Null selector*/
  40.898 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
  40.899 +                                cpl_override=1;
  40.900 +                                if (tempi)
  40.901 +                                {
  40.902 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
  40.903 +                                }
  40.904 +                                cpl_override=0;
  40.905 +                                if (abrt) break;
  40.906 +                                if ((tempw2&0x1400)==0x400) tempi=0; /*Interrupt or trap or call gate*/
  40.907 +                                if ((tempw2&0x1F00)==0x000) tempi=0; /*Invalid*/
  40.908 +                                if ((tempw2&0x1F00)==0xA00) tempi=0; /*Invalid*/
  40.909 +                                if ((tempw2&0x1C00)!=0x1C00) /*Exclude conforming code segments*/
  40.910 +                                {
  40.911 +                                        tempw3=(tempw2>>13)&3;
  40.912 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
  40.913 +                                }
  40.914 +                                if (tempi)
  40.915 +                                {
  40.916 +                                        flags|=Z_FLAG;
  40.917 +                                        cpl_override=1;
  40.918 +                                        regs[reg].w=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7));
  40.919 +                                        cpl_override=0;
  40.920 +                                }
  40.921 +                                cycles -= (mod == 3) ? 14 : 16;
  40.922 +                                break;
  40.923 +
  40.924 +                                case 5: /*LOADALL*/
  40.925 +//                                pclog("At %04X:%04X  ",CS,pc);
  40.926 +                                flags=(readmemw(0,0x818)&0xFFD5)|2;
  40.927 +                                pc=readmemw(0,0x81A);
  40.928 +                                DS=readmemw(0,0x81E);
  40.929 +                                SS=readmemw(0,0x820);
  40.930 +                                CS=readmemw(0,0x822);
  40.931 +                                ES=readmemw(0,0x824);
  40.932 +                                DI=readmemw(0,0x826);
  40.933 +                                SI=readmemw(0,0x828);
  40.934 +                                BP=readmemw(0,0x82A);
  40.935 +                                SP=readmemw(0,0x82C);
  40.936 +                                BX=readmemw(0,0x82E);
  40.937 +                                DX=readmemw(0,0x830);
  40.938 +                                CX=readmemw(0,0x832);
  40.939 +                                AX=readmemw(0,0x834);
  40.940 +                                /*if (readmemw(0,0x806))
  40.941 +                                {
  40.942 +                                        pclog("Something in LOADALL!\n");
  40.943 +                                        dumpregs();
  40.944 +                                        exit(-1);
  40.945 +                                }*/
  40.946 +                                es=readmemw(0,0x836)|(readmemb(0,0x838)<<16);
  40.947 +                                cs=readmemw(0,0x83C)|(readmemb(0,0x83E)<<16);
  40.948 +                                ss=readmemw(0,0x842)|(readmemb(0,0x844)<<16);
  40.949 +                                ds=readmemw(0,0x848)|(readmemb(0,0x84A)<<16);
  40.950 +                                cycles-=195;
  40.951 +//                                pclog("LOADALL - %06X:%04X %06X:%04X %04X\n",ds,SI,es,DI,DX);
  40.952 +                                break;
  40.953 +                                
  40.954 +                                case 6: /*CLTS*/
  40.955 +                                if (CPL && (msw & 1))
  40.956 +                                {
  40.957 +                                        pclog("Can't CLTS\n");
  40.958 +                                        x86gpf(NULL,0);
  40.959 +                                        break;
  40.960 +                                }
  40.961 +                                msw &= ~8;
  40.962 +                                cycles-=2;
  40.963 +                                break;
  40.964 +                                
  40.965 +                                case 0xFF: /*Invalid - Windows 3.1 syscall trap?*/
  40.966 +                                inv16:
  40.967 +                                pc-=2;
  40.968 +                                if (msw&1)
  40.969 +                                {
  40.970 +                                        pmodeint(6,0);
  40.971 +                                }
  40.972 +                                else
  40.973 +                                {
  40.974 +                                        if (ssegs) ss=oldss;
  40.975 +                                        writememw(ss,((SP-2)&0xFFFF),flags);
  40.976 +                                        writememw(ss,((SP-4)&0xFFFF),CS);
  40.977 +                                        writememw(ss,((SP-6)&0xFFFF),pc);
  40.978 +                                        SP-=6;
  40.979 +                                        addr=6<<2;
  40.980 +                                        flags&=~I_FLAG;
  40.981 +                                        flags&=~T_FLAG;
  40.982 +                                        oxpc=pc;
  40.983 +                                        pc=readmemw(0,addr);
  40.984 +                                        loadcs(readmemw(0,addr+2));
  40.985 +/*                                        if (!pc && !cs)
  40.986 +                                        {
  40.987 +                                                pclog("Bad int %02X %04X:%04X\n",temp,oldcs,oldpc);
  40.988 +                                                dumpregs();
  40.989 +                                                exit(-1);
  40.990 +                                        }*/
  40.991 +                                }
  40.992 +                                cycles-=23;
  40.993 +                                break;
  40.994 +
  40.995 +                                default:
  40.996 +                                pclog("Bad 16-bit 0F opcode %02X 386 %i\n",temp,ins);
  40.997 +                                pc=oldpc;
  40.998 +//                                output=3;
  40.999 +//                                timetolive=100000;
 40.1000 +//                                dumpregs();
 40.1001 +//                                exit(-1);
 40.1002 +                                x86illegal();
 40.1003 +                                break;
 40.1004 +                        }
 40.1005 +                        break;
 40.1006 +
 40.1007 +                        case 0x10: /*ADC 8,reg*/
 40.1008 +                        fetchea();
 40.1009 +                        if (mod == 3)
 40.1010 +                        {
 40.1011 +                                temp  = getr8(rm);
 40.1012 +                                temp2 = getr8(reg);
 40.1013 +                                setadc8(temp, temp2);
 40.1014 +                                setr8(rm, temp + temp2 + tempc);
 40.1015 +                                cycles -= 2;
 40.1016 +                        }
 40.1017 +                        else
 40.1018 +                        {
 40.1019 +                                temp  = geteab();               if (abrt) break;
 40.1020 +                                temp2 = getr8(reg);
 40.1021 +                                seteab(temp + temp2 + tempc);   if (abrt) break;
 40.1022 +                                setadc8(temp, temp2);
 40.1023 +                                cycles -= 7;
 40.1024 +                        }
 40.1025 +                        break;
 40.1026 +                        case 0x11: /*ADC 16,reg*/
 40.1027 +                        fetchea();
 40.1028 +                        if (mod == 3)
 40.1029 +                        {
 40.1030 +                                setadc16(regs[rm].w, regs[reg].w);
 40.1031 +                                regs[rm].w += regs[reg].w + tempc;
 40.1032 +                                cycles -= 2;
 40.1033 +                        }
 40.1034 +                        else
 40.1035 +                        {
 40.1036 +                                tempw  = geteaw();              if (abrt) break;
 40.1037 +                                tempw2 = regs[reg].w;
 40.1038 +                                seteaw(tempw + tempw2 + tempc); if (abrt) break;
 40.1039 +                                setadc16(tempw, tempw2);
 40.1040 +                                cycles -= 7;
 40.1041 +                        }
 40.1042 +                        break;
 40.1043 +                        case 0x12: /*ADC reg,8*/
 40.1044 +                        fetchea();
 40.1045 +                        temp=geteab();                  if (abrt) break;
 40.1046 +                        setadc8(getr8(reg),temp);
 40.1047 +                        setr8(reg,getr8(reg)+temp+tempc);
 40.1048 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1049 +                        break;
 40.1050 +                        case 0x13: /*ADC reg,16*/
 40.1051 +                        fetchea();
 40.1052 +                        tempw=geteaw();                 if (abrt) break;
 40.1053 +                        setadc16(regs[reg].w,tempw);
 40.1054 +                        regs[reg].w+=tempw+tempc;
 40.1055 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1056 +                        break;
 40.1057 +                        case 0x14: /*ADC AL,#8*/
 40.1058 +                        tempw=getbytef();
 40.1059 +                        setadc8(AL,tempw);
 40.1060 +                        AL+=tempw+tempc;
 40.1061 +                        cycles -= 3;
 40.1062 +                        break;
 40.1063 +                        case 0x15: /*ADC AX,#16*/
 40.1064 +                        tempw=getwordf();
 40.1065 +                        setadc16(AX,tempw);
 40.1066 +                        AX+=tempw+tempc;
 40.1067 +                        cycles -= 3;
 40.1068 +                        break;
 40.1069 +
 40.1070 +                        case 0x16: /*PUSH SS*/
 40.1071 +                        if (ssegs) ss=oldss;
 40.1072 +                        writememw(ss,((SP-2)&0xFFFF),SS); if (abrt) break;
 40.1073 +                        SP-=2;
 40.1074 +                        cycles-=3;
 40.1075 +                        break;
 40.1076 +                        case 0x17: /*POP SS*/
 40.1077 +                        if (ssegs) ss=oldss;
 40.1078 +                        tempw=readmemw(ss,SP);  if (abrt) break;
 40.1079 +                        loadseg(tempw,&_ss); if (abrt) break;
 40.1080 +                        SP += 2;
 40.1081 +                        cycles -= (msw & 1) ? 20 : 5;
 40.1082 +                        break;
 40.1083 +
 40.1084 +                        case 0x18: /*SBB 8,reg*/
 40.1085 +                        fetchea();
 40.1086 +                        if (mod == 3)
 40.1087 +                        {
 40.1088 +                                temp  = getr8(rm);
 40.1089 +                                temp2 = getr8(reg);
 40.1090 +                                setsbc8(temp, temp2);
 40.1091 +                                setr8(rm, temp - (temp2 + tempc));
 40.1092 +                                cycles -= 2;
 40.1093 +                        }
 40.1094 +                        else
 40.1095 +                        {
 40.1096 +                                temp  = geteab();                  if (abrt) break;
 40.1097 +                                temp2 = getr8(reg);
 40.1098 +                                seteab(temp - (temp2 + tempc));    if (abrt) break;
 40.1099 +                                setsbc8(temp, temp2);
 40.1100 +                                cycles -= 7;
 40.1101 +                        }
 40.1102 +                        break;
 40.1103 +                        case 0x19: /*SBB 16,reg*/
 40.1104 +                        fetchea();
 40.1105 +                        if (mod == 3)
 40.1106 +                        {
 40.1107 +                                setsbc16(regs[rm].w, regs[reg].w);
 40.1108 +                                regs[rm].w -= (regs[reg].w + tempc);
 40.1109 +                                cycles -= 2;
 40.1110 +                        }
 40.1111 +                        else
 40.1112 +                        {
 40.1113 +                                tempw  = geteaw();                 if (abrt) break;
 40.1114 +                                tempw2 = regs[reg].w;
 40.1115 +                                seteaw(tempw - (tempw2 + tempc));  if (abrt) break;
 40.1116 +                                setsbc16(tempw, tempw2);
 40.1117 +                                cycles -= 7;
 40.1118 +                        }
 40.1119 +                        break;
 40.1120 +                        case 0x1A: /*SBB reg,8*/
 40.1121 +                        fetchea();
 40.1122 +                        temp=geteab();                  if (abrt) break;
 40.1123 +                        setsbc8(getr8(reg),temp);
 40.1124 +                        setr8(reg,getr8(reg)-(temp+tempc));
 40.1125 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1126 +                        break;
 40.1127 +                        case 0x1B: /*SBB reg,16*/
 40.1128 +                        fetchea();
 40.1129 +                        tempw=geteaw();                 if (abrt) break;
 40.1130 +                        tempw2=regs[reg].w;
 40.1131 +                        setsbc16(tempw2,tempw);
 40.1132 +                        tempw2-=(tempw+tempc);
 40.1133 +                        regs[reg].w=tempw2;
 40.1134 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1135 +                        break;
 40.1136 +                        case 0x1C: /*SBB AL,#8*/
 40.1137 +                        temp=getbytef();
 40.1138 +                        setsbc8(AL,temp);
 40.1139 +                        AL-=(temp+tempc);
 40.1140 +                        cycles -= 3;
 40.1141 +                        break;
 40.1142 +                        case 0x1D: /*SBB AX,#16*/
 40.1143 +                        tempw=getwordf();
 40.1144 +                        setsbc16(AX,tempw);
 40.1145 +                        AX-=(tempw+tempc);
 40.1146 +                        cycles -= 3;
 40.1147 +                        break;
 40.1148 +
 40.1149 +                        case 0x1E: /*PUSH DS*/
 40.1150 +                        if (ssegs) ss=oldss;
 40.1151 +                        writememw(ss,((SP-2)&0xFFFF),DS);       if (abrt) break;
 40.1152 +                        SP-=2;
 40.1153 +                        cycles-=3;
 40.1154 +                        break;
 40.1155 +                        case 0x1F: case 0x21F: /*POP DS*/
 40.1156 +                        if (ssegs) ss=oldss;
 40.1157 +                        tempw=readmemw(ss,SP);                  if (abrt) break;
 40.1158 +                        loadseg(tempw,&_ds); if (abrt) break;
 40.1159 +                        SP+=2;
 40.1160 +                        cycles -= (msw & 1) ? 20 : 5;
 40.1161 +                        break;
 40.1162 +
 40.1163 +                        case 0x20: /*AND 8,reg*/
 40.1164 +                        fetchea();
 40.1165 +                        if (mod == 3)
 40.1166 +                        {
 40.1167 +                                temp  = getr8(rm) & getr8(reg);
 40.1168 +                                setr8(rm, temp);
 40.1169 +                                setznp8(temp);
 40.1170 +                                cycles -= 2;
 40.1171 +                        }
 40.1172 +                        else
 40.1173 +                        {
 40.1174 +                                temp  = geteab();    if (abrt) break;
 40.1175 +                                temp &= getr8(reg);
 40.1176 +                                seteab(temp);        if (abrt) break;
 40.1177 +                                setznp8(temp);
 40.1178 +                                cycles -= 7;
 40.1179 +                        }
 40.1180 +                        break;
 40.1181 +                        case 0x21: /*AND 16,reg*/
 40.1182 +                        fetchea();
 40.1183 +                        if (mod == 3)
 40.1184 +                        {
 40.1185 +                                regs[rm].w &= regs[reg].w;
 40.1186 +                                setznp16(regs[rm].w);
 40.1187 +                                cycles -= 2;
 40.1188 +                        }
 40.1189 +                        else
 40.1190 +                        {
 40.1191 +                                tempw = geteaw() & regs[reg].w; if (abrt) break;
 40.1192 +                                seteaw(tempw);                  if (abrt) break;
 40.1193 +                                setznp16(tempw);
 40.1194 +                                cycles -= 7;
 40.1195 +                        }
 40.1196 +                        break;
 40.1197 +                        case 0x22: /*AND reg,8*/
 40.1198 +                        fetchea();
 40.1199 +                        temp=geteab();          if (abrt) break;
 40.1200 +                        temp&=getr8(reg);
 40.1201 +                        setznp8(temp);
 40.1202 +                        setr8(reg,temp);
 40.1203 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1204 +                        break;
 40.1205 +                        case 0x23: /*AND reg,16*/
 40.1206 +                        fetchea();
 40.1207 +                        tempw=geteaw();         if (abrt) break;
 40.1208 +                        tempw&=regs[reg].w;
 40.1209 +                        setznp16(tempw);
 40.1210 +                        regs[reg].w=tempw;
 40.1211 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1212 +                        break;
 40.1213 +                        case 0x24: /*AND AL,#8*/
 40.1214 +                        AL&=getbytef();
 40.1215 +                        setznp8(AL);
 40.1216 +                        cycles -= 3;
 40.1217 +                        break;
 40.1218 +                        case 0x25: /*AND AX,#16*/
 40.1219 +                        AX&=getwordf();
 40.1220 +                        setznp16(AX);
 40.1221 +                        cycles -= 3;
 40.1222 +                        break;
 40.1223 +
 40.1224 +                        case 0x26: /*ES:*/
 40.1225 +                        oldss=ss;
 40.1226 +                        oldds=ds;
 40.1227 +                        ds=ss=es;
 40.1228 +                        rds=ES;
 40.1229 +                        ssegs=2;
 40.1230 +                        cycles-=2;
 40.1231 +                        goto opcodestart;
 40.1232 +//                        break;
 40.1233 +
 40.1234 +                        case 0x27: /*DAA*/
 40.1235 +                        if ((flags & A_FLAG) || ((AL & 0xF) > 9))
 40.1236 +                        {
 40.1237 +                                tempi = ((uint16_t)AL) + 6;
 40.1238 +                                AL += 6;
 40.1239 +                                flags |= A_FLAG;
 40.1240 +                                if (tempi & 0x100) flags |= C_FLAG;
 40.1241 +                        }
 40.1242 +                        if ((flags&C_FLAG) || (AL>0x9F))
 40.1243 +                        {
 40.1244 +                                AL+=0x60;
 40.1245 +                                flags|=C_FLAG;
 40.1246 +                        }
 40.1247 +                        tempw = flags & (C_FLAG | A_FLAG);
 40.1248 +                        setznp8(AL);
 40.1249 +                        flags |= tempw;
 40.1250 +                        cycles -= 3;
 40.1251 +                        break;
 40.1252 +
 40.1253 +                        case 0x28: /*SUB 8,reg*/
 40.1254 +                        fetchea();
 40.1255 +                        if (mod == 3)
 40.1256 +                        {
 40.1257 +                                temp  = getr8(rm);
 40.1258 +                                temp2 = getr8(reg);
 40.1259 +                                setsub8(temp, temp2);
 40.1260 +                                setr8(rm, temp - temp2);
 40.1261 +                                cycles -= 2;
 40.1262 +                        }
 40.1263 +                        else
 40.1264 +                        {
 40.1265 +                                temp  = geteab();     if (abrt) break;
 40.1266 +                                temp2 = getr8(reg);
 40.1267 +                                seteab(temp - temp2); if (abrt) break;
 40.1268 +                                setsub8(temp, temp2);
 40.1269 +                                cycles -= 7;
 40.1270 +                        }
 40.1271 +                        break;
 40.1272 +                        case 0x29: /*SUB 16,reg*/
 40.1273 +                        fetchea();
 40.1274 +                        if (mod == 3)
 40.1275 +                        {
 40.1276 +                                setsub16(regs[rm].w, regs[reg].w);
 40.1277 +                                regs[rm].w -= regs[reg].w;
 40.1278 +                                cycles -= 2;
 40.1279 +                        }
 40.1280 +                        else
 40.1281 +                        {
 40.1282 +                                tempw = geteaw();             if (abrt) break;
 40.1283 +                                seteaw(tempw - regs[reg].w);  if (abrt) break;
 40.1284 +                                setsub16(tempw, regs[reg].w);
 40.1285 +                                cycles -= 7;
 40.1286 +                        }
 40.1287 +                        break;
 40.1288 +                        case 0x2A: /*SUB reg,8*/
 40.1289 +                        fetchea();
 40.1290 +                        temp=geteab();          if (abrt) break;
 40.1291 +                        setsub8(getr8(reg),temp);
 40.1292 +                        setr8(reg,getr8(reg)-temp);
 40.1293 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1294 +                        break;
 40.1295 +                        case 0x2B: /*SUB reg,16*/
 40.1296 +                        fetchea();
 40.1297 +                        tempw=geteaw();         if (abrt) break;
 40.1298 +                        setsub16(regs[reg].w,tempw);
 40.1299 +                        regs[reg].w-=tempw;
 40.1300 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1301 +                        break;
 40.1302 +                        case 0x2C: /*SUB AL,#8*/
 40.1303 +                        temp=getbytef();
 40.1304 +                        setsub8(AL,temp);
 40.1305 +                        AL-=temp;
 40.1306 +                        cycles -= 3;
 40.1307 +                        break;
 40.1308 +                        case 0x2D: /*SUB AX,#16*/
 40.1309 +                        tempw=getwordf();
 40.1310 +                        setsub16(AX,tempw);
 40.1311 +                        AX-=tempw;
 40.1312 +                        cycles -= 3;
 40.1313 +                        break;
 40.1314 +
 40.1315 +                        case 0x2E: /*CS:*/
 40.1316 +                        oldss=ss;
 40.1317 +                        oldds=ds;
 40.1318 +                        ds=ss=cs;
 40.1319 +                        rds=CS;
 40.1320 +                        ssegs=2;
 40.1321 +                        cycles-=2;
 40.1322 +                        goto opcodestart;
 40.1323 +                        
 40.1324 +                        case 0x2F: /*DAS*/
 40.1325 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 40.1326 +                        {
 40.1327 +                                tempi=((uint16_t)AL)-6;
 40.1328 +                                AL-=6;
 40.1329 +                                flags|=A_FLAG;
 40.1330 +                                if (tempi&0x100) flags|=C_FLAG;
 40.1331 +                        }
 40.1332 +//                        else
 40.1333 +//                           flags&=~A_FLAG;
 40.1334 +                        if ((flags&C_FLAG)||(AL>0x9F))
 40.1335 +                        {
 40.1336 +                                AL-=0x60;
 40.1337 +                                flags|=C_FLAG;
 40.1338 +                        }
 40.1339 +//                        else
 40.1340 +//                           flags&=~C_FLAG;
 40.1341 +                        tempw = flags & (C_FLAG | A_FLAG);
 40.1342 +                        setznp8(AL);
 40.1343 +                        flags |= tempw;
 40.1344 +                        cycles -= 3;
 40.1345 +                        break;
 40.1346 +
 40.1347 +                        case 0x30: /*XOR 8,reg*/
 40.1348 +                        fetchea();
 40.1349 +                        if (mod == 3)
 40.1350 +                        {
 40.1351 +                                temp = getr8(rm) ^ getr8(reg);
 40.1352 +                                setr8(rm, temp);
 40.1353 +                                setznp8(temp);
 40.1354 +                                cycles -= 2;
 40.1355 +                        }
 40.1356 +                        else
 40.1357 +                        {
 40.1358 +                                temp  = geteab();    if (abrt) break;
 40.1359 +                                temp ^= getr8(reg);
 40.1360 +                                seteab(temp);        if (abrt) break;
 40.1361 +                                setznp8(temp);
 40.1362 +                                cycles -= 7;
 40.1363 +                        }
 40.1364 +                        break;
 40.1365 +                        case 0x31: /*XOR 16,reg*/
 40.1366 +                        fetchea();
 40.1367 +                        if (mod == 3)
 40.1368 +                        {
 40.1369 +                                regs[rm].w ^= regs[reg].w;
 40.1370 +                                setznp16(regs[rm].w);
 40.1371 +                                cycles -= 2;
 40.1372 +                        }
 40.1373 +                        else
 40.1374 +                        {
 40.1375 +                                tempw = geteaw() ^ regs[reg].w; if (abrt) break;
 40.1376 +                                seteaw(tempw);                  if (abrt) break;
 40.1377 +                                setznp16(tempw);
 40.1378 +                                cycles -= 7;
 40.1379 +                        }
 40.1380 +                        break;
 40.1381 +                        case 0x32: /*XOR reg,8*/
 40.1382 +                        fetchea();
 40.1383 +                        temp=geteab();          if (abrt) break;
 40.1384 +                        temp^=getr8(reg);
 40.1385 +                        setznp8(temp);
 40.1386 +                        setr8(reg,temp);
 40.1387 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1388 +                        break;
 40.1389 +                        case 0x33: /*XOR reg,16*/
 40.1390 +                        fetchea();
 40.1391 +                        tempw=geteaw();         if (abrt) break;
 40.1392 +                        tempw^=regs[reg].w;
 40.1393 +                        setznp16(tempw);
 40.1394 +                        regs[reg].w=tempw;
 40.1395 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1396 +                        break;
 40.1397 +                        case 0x34: /*XOR AL,#8*/
 40.1398 +                        AL^=getbytef();
 40.1399 +                        setznp8(AL);
 40.1400 +                        cycles -= 3;
 40.1401 +                        break;
 40.1402 +                        case 0x35: /*XOR AX,#16*/
 40.1403 +                        AX^=getwordf();
 40.1404 +                        setznp16(AX);
 40.1405 +                        cycles -= 3;
 40.1406 +                        break;
 40.1407 +
 40.1408 +                        case 0x36: /*SS:*/
 40.1409 +                        oldss=ss;
 40.1410 +                        oldds=ds;
 40.1411 +                        ds=ss=ss;
 40.1412 +                        rds=SS;
 40.1413 +                        ssegs=2;
 40.1414 +                        cycles-=2;
 40.1415 +                        goto opcodestart;
 40.1416 +//                        break;
 40.1417 +
 40.1418 +                        case 0x37: /*AAA*/
 40.1419 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 40.1420 +                        {
 40.1421 +                                AL+=6;
 40.1422 +                                AH++;
 40.1423 +                                flags|=(A_FLAG|C_FLAG);
 40.1424 +                        }
 40.1425 +                        else
 40.1426 +                           flags&=~(A_FLAG|C_FLAG);
 40.1427 +                        AL&=0xF;
 40.1428 +                        cycles -= 3;
 40.1429 +                        break;
 40.1430 +
 40.1431 +                        case 0x38: /*CMP 8,reg*/
 40.1432 +                        fetchea();
 40.1433 +                        temp=geteab();          if (abrt) break;
 40.1434 +                        setsub8(temp,getr8(reg));
 40.1435 +                        cycles -= (mod == 3) ? 2 : 7;
 40.1436 +                        break;
 40.1437 +                        case 0x39: /*CMP 16,reg*/
 40.1438 +                        fetchea();
 40.1439 +                        tempw=geteaw();         if (abrt) break;
 40.1440 +//                        if (output) pclog("CMP %04X %04X\n",tempw,regs[reg].w);
 40.1441 +                        setsub16(tempw,regs[reg].w);
 40.1442 +                        cycles -= (mod == 3) ? 2 : 7;                        
 40.1443 +                        break;
 40.1444 +                        case 0x3A: /*CMP reg,8*/
 40.1445 +                        fetchea();
 40.1446 +                        temp=geteab();          if (abrt) break;
 40.1447 +//                        if (output) pclog("CMP %02X-%02X\n",getr8(reg),temp);
 40.1448 +                        setsub8(getr8(reg),temp);
 40.1449 +                        cycles -= (mod == 3) ? 2 : 6;
 40.1450 +                        break;
 40.1451 +                        case 0x3B: /*CMP reg,16*/
 40.1452 +                        fetchea();
 40.1453 +                        tempw=geteaw();         if (abrt) break;
 40.1454 +                        setsub16(regs[reg].w,tempw);
 40.1455 +                        cycles -= (mod == 3) ? 2 : 6;
 40.1456 +                        break;
 40.1457 +                        case 0x3C: /*CMP AL,#8*/
 40.1458 +                        temp=getbytef();
 40.1459 +                        setsub8(AL,temp);
 40.1460 +                        cycles -= 3;
 40.1461 +                        break;
 40.1462 +                        case 0x3D: /*CMP AX,#16*/
 40.1463 +                        tempw=getwordf();
 40.1464 +                        setsub16(AX,tempw);
 40.1465 +                        cycles -= 3;
 40.1466 +                        break;
 40.1467 +
 40.1468 +                        case 0x3E: /*DS:*/
 40.1469 +                        oldss=ss;
 40.1470 +                        oldds=ds;
 40.1471 +                        ds=ss=ds;
 40.1472 +                        ssegs=2;
 40.1473 +                        cycles-=2;
 40.1474 +                        goto opcodestart;
 40.1475 +//                        break;
 40.1476 +
 40.1477 +                        case 0x3F: /*AAS*/
 40.1478 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 40.1479 +                        {
 40.1480 +                                AL-=6;
 40.1481 +                                AH--;
 40.1482 +                                flags|=(A_FLAG|C_FLAG);
 40.1483 +                        }
 40.1484 +                        else
 40.1485 +                           flags&=~(A_FLAG|C_FLAG);
 40.1486 +                        AL&=0xF;
 40.1487 +                        cycles -= 3;
 40.1488 +                        break;
 40.1489 +
 40.1490 +                        case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
 40.1491 +                        case 0x44: case 0x45: case 0x46: case 0x47:
 40.1492 +                        setadd16nc(regs[opcode&7].w,1);
 40.1493 +                        regs[opcode&7].w++;
 40.1494 +                        cycles -= 2;
 40.1495 +                        break;
 40.1496 +                        case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/
 40.1497 +                        case 0x4C: case 0x4D: case 0x4E: case 0x4F:
 40.1498 +                        setsub16nc(regs[opcode&7].w,1);
 40.1499 +                        regs[opcode&7].w--;
 40.1500 +                        cycles -= 2;
 40.1501 +                        break;
 40.1502 +
 40.1503 +                        case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
 40.1504 +                        case 0x54: case 0x55: case 0x56: case 0x57:
 40.1505 +                        if (ssegs) ss=oldss;
 40.1506 +                        writememw(ss,(SP-2)&0xFFFF,regs[opcode&7].w);   if (abrt) break;
 40.1507 +                        SP-=2;
 40.1508 +                        cycles -= 3;
 40.1509 +                        break;
 40.1510 +                        case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/
 40.1511 +                        case 0x5C: case 0x5D: case 0x5E: case 0x5F:
 40.1512 +                        if (ssegs) ss=oldss;
 40.1513 +                        SP+=2;
 40.1514 +                        tempw=readmemw(ss,(SP-2)&0xFFFF);    if (abrt) { SP-=2; break; }
 40.1515 +                        regs[opcode&7].w=tempw;
 40.1516 +                        cycles -= 5;
 40.1517 +                        break;
 40.1518 +
 40.1519 +                        case 0x60: /*PUSHA*/
 40.1520 +                        writememw(ss,((SP-2)&0xFFFF),AX);
 40.1521 +                        writememw(ss,((SP-4)&0xFFFF),CX);
 40.1522 +                        writememw(ss,((SP-6)&0xFFFF),DX);
 40.1523 +                        writememw(ss,((SP-8)&0xFFFF),BX);
 40.1524 +                        writememw(ss,((SP-10)&0xFFFF),SP);
 40.1525 +                        writememw(ss,((SP-12)&0xFFFF),BP);
 40.1526 +                        writememw(ss,((SP-14)&0xFFFF),SI);
 40.1527 +                        writememw(ss,((SP-16)&0xFFFF),DI);
 40.1528 +                        if (!abrt) SP-=16;
 40.1529 +                        cycles -= 17;
 40.1530 +                        break;
 40.1531 +                        case 0x61: /*POPA*/
 40.1532 +                        DI=readmemw(ss,((SP)&0xFFFF));          if (abrt) break;
 40.1533 +                        SI=readmemw(ss,((SP+2)&0xFFFF));        if (abrt) break;
 40.1534 +                        BP=readmemw(ss,((SP+4)&0xFFFF));        if (abrt) break;
 40.1535 +                        BX=readmemw(ss,((SP+8)&0xFFFF));        if (abrt) break;
 40.1536 +                        DX=readmemw(ss,((SP+10)&0xFFFF));       if (abrt) break;
 40.1537 +                        CX=readmemw(ss,((SP+12)&0xFFFF));       if (abrt) break;
 40.1538 +                        AX=readmemw(ss,((SP+14)&0xFFFF));       if (abrt) break;
 40.1539 +                        SP+=16;
 40.1540 +                        cycles -= 19;
 40.1541 +                        break;
 40.1542 +
 40.1543 +                        case 0x62: /*BOUND*/
 40.1544 +                        fetchea();
 40.1545 +                        tempw=geteaw();
 40.1546 +                        tempw2=readmemw(easeg,eaaddr+2); if (abrt) break;
 40.1547 +                        if (((int16_t)regs[reg].w<(int16_t)tempw) || ((int16_t)regs[reg].w>(int16_t)tempw2))
 40.1548 +                        {
 40.1549 +                                x86_int(5);
 40.1550 +                        }
 40.1551 +                        cycles -= 13;
 40.1552 +                        break;
 40.1553 +                        
 40.1554 +                        case 0x63: /*ARPL*/
 40.1555 +                        NOTRM
 40.1556 +                        fetchea();
 40.1557 +                        tempw=geteaw(); if (abrt) break;
 40.1558 +                        if ((tempw&3)<(regs[reg].w&3))
 40.1559 +                        {
 40.1560 +                                tempw=(tempw&0xFFFC)|(regs[reg].w&3);
 40.1561 +                                seteaw(tempw); if (abrt) break;
 40.1562 +                                flags|=Z_FLAG;
 40.1563 +                        }
 40.1564 +                        else
 40.1565 +                           flags&=~Z_FLAG;
 40.1566 +                        cycles -= (mod == 3) ? 10 : 11;
 40.1567 +                        break;
 40.1568 +
 40.1569 +                        case 0x68: /*PUSH #w*/
 40.1570 +                        tempw=getword();
 40.1571 +                        writememw(ss,((SP-2)&0xFFFF),tempw);    if (abrt) break;
 40.1572 +                        SP-=2;
 40.1573 +                        cycles -= 3;
 40.1574 +                        break;
 40.1575 +                        case 0x69: /*IMUL r16*/
 40.1576 +                        fetchea();
 40.1577 +                        tempw=geteaw();         if (abrt) break;
 40.1578 +                        tempw2=getword();       if (abrt) break;
 40.1579 +                        templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2);
 40.1580 +                        if ((templ>>16)!=0 && (templ>>16)!=0xFFFF) flags|=C_FLAG|V_FLAG;
 40.1581 +                        else                                       flags&=~(C_FLAG|V_FLAG);
 40.1582 +                        regs[reg].w=templ&0xFFFF;
 40.1583 +                        cycles -= (mod == 3) ? 21 : 24;
 40.1584 +                        break;
 40.1585 +                        case 0x6A: /*PUSH #eb*/
 40.1586 +                        tempw=readmemb(cs,pc); pc++;
 40.1587 +                        if (tempw&0x80) tempw|=0xFF00;
 40.1588 +                        writememw(ss,((SP-2)&0xFFFF),tempw);    if (abrt) break;
 40.1589 +                        SP-=2;
 40.1590 +                        cycles -= 3;
 40.1591 +                        break;
 40.1592 +                        case 0x6B: /*IMUL r8*/
 40.1593 +                        fetchea();
 40.1594 +                        tempw=geteaw();                 if (abrt) break;
 40.1595 +                        tempw2=readmemb(cs,pc); pc++;   if (abrt) break;
 40.1596 +                        if (tempw2&0x80) tempw2|=0xFF00;
 40.1597 +                        templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2);
 40.1598 +                        if ((templ>>16)!=0 && ((templ>>16)&0xFFFF)!=0xFFFF) flags|=C_FLAG|V_FLAG;
 40.1599 +                        else                                                flags&=~(C_FLAG|V_FLAG);
 40.1600 +                        regs[reg].w=templ&0xFFFF;
 40.1601 +                        cycles -= (mod == 3) ? 21 : 24;
 40.1602 +                        break;
 40.1603 +
 40.1604 +                        case 0x6C: /*INSB*/
 40.1605 +                        checkio_perm(DX);
 40.1606 +                        temp=inb(DX);
 40.1607 +                        writememb(es,DI,temp);          if (abrt) break;
 40.1608 +                        if (flags&D_FLAG) DI--;
 40.1609 +                        else              DI++;
 40.1610 +                        cycles -= 5;
 40.1611 +                        break;
 40.1612 +                        case 0x6D: /*INSW*/
 40.1613 +                        checkio_perm(DX);
 40.1614 +                        checkio_perm(DX+1);
 40.1615 +                        tempw=inw(DX);
 40.1616 +                        writememw(es,DI,tempw);         if (abrt) break;
 40.1617 +                        if (flags&D_FLAG) DI-=2;
 40.1618 +                        else              DI+=2;
 40.1619 +                        cycles -= 5;
 40.1620 +                        break;
 40.1621 +                        case 0x6E: /*OUTSB*/
 40.1622 +                        temp=readmemb(ds,SI);           if (abrt) break;
 40.1623 +                        checkio_perm(DX);
 40.1624 +                        if (flags&D_FLAG) SI--;
 40.1625 +                        else              SI++;
 40.1626 +                        outb(DX,temp);
 40.1627 +                        cycles -= 5;
 40.1628 +                        break;
 40.1629 +                        case 0x6F: /*OUTSW*/
 40.1630 +                        tempw=readmemw(ds,SI);          if (abrt) break;
 40.1631 +                        checkio_perm(DX);
 40.1632 +                        checkio_perm(DX+1);
 40.1633 +                        if (flags&D_FLAG) SI-=2;
 40.1634 +                        else              SI+=2;
 40.1635 +                        outw(DX,tempw);
 40.1636 +//                        outb(DX+1,tempw>>8);
 40.1637 +                        cycles -= 5;
 40.1638 +                        break;
 40.1639 +
 40.1640 +                        case 0x70: /*JO*/
 40.1641 +                        offset=(int8_t)getbytef();
 40.1642 +                        if (flags&V_FLAG) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1643 +                        cycles -= 3;
 40.1644 +                        break;
 40.1645 +                        case 0x71: /*JNO*/
 40.1646 +                        offset=(int8_t)getbytef();
 40.1647 +                        if (!(flags&V_FLAG)) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1648 +                        cycles -= 3;
 40.1649 +                        break;
 40.1650 +                        case 0x72: /*JB*/
 40.1651 +                        offset=(int8_t)getbytef();
 40.1652 +                        if (flags&C_FLAG) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1653 +                        cycles -= 3;
 40.1654 +                        break;
 40.1655 +                        case 0x73: /*JNB*/
 40.1656 +                        offset=(int8_t)getbytef();
 40.1657 +                        if (!(flags&C_FLAG)) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1658 +                        cycles -= 3;
 40.1659 +                        break;
 40.1660 +                        case 0x74: /*JZ*/
 40.1661 +                        offset=(int8_t)getbytef();
 40.1662 +                        if (flags&Z_FLAG) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1663 +                        cycles -= 3;
 40.1664 +                        break;
 40.1665 +                        case 0x75: /*JNZ*/
 40.1666 +                        offset=(int8_t)getbytef();
 40.1667 +                        if (!(flags&Z_FLAG)) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1668 +                        cycles -= 3;
 40.1669 +                        break;
 40.1670 +                        case 0x76: /*JBE*/
 40.1671 +                        offset=(int8_t)getbytef();
 40.1672 +                        if (flags&(C_FLAG|Z_FLAG)) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1673 +                        cycles -= 3;
 40.1674 +                        break;
 40.1675 +                        case 0x77: /*JNBE*/
 40.1676 +                        offset=(int8_t)getbytef();
 40.1677 +                        if (!(flags&(C_FLAG|Z_FLAG))) { pc += offset; cycles -= 4; cycles -= 2; }
 40.1678 +                        cycles -= 3;
 40.1679 +                        break;
 40.1680 +                        case 0x78: /*JS*/
 40.1681 +                        offset=(int8_t)getbytef();
 40.1682 +                        if (flags&N_FLAG)  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1683 +                        cycles -= 3;
 40.1684 +                        break;
 40.1685 +                        case 0x79: /*JNS*/
 40.1686 +                        offset=(int8_t)getbytef();
 40.1687 +                        if (!(flags&N_FLAG))  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1688 +                        cycles -= 3;
 40.1689 +                        break;
 40.1690 +                        case 0x7A: /*JP*/
 40.1691 +                        offset=(int8_t)getbytef();
 40.1692 +                        if (flags&P_FLAG)  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1693 +                        cycles -= 3;
 40.1694 +                        break;
 40.1695 +                        case 0x7B: /*JNP*/
 40.1696 +                        offset=(int8_t)getbytef();
 40.1697 +                        if (!(flags&P_FLAG))  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1698 +                        cycles -= 3;
 40.1699 +                        break;
 40.1700 +                        case 0x7C: /*JL*/
 40.1701 +                        offset=(int8_t)getbytef();
 40.1702 +                        temp=(flags&N_FLAG)?1:0;
 40.1703 +                        temp2=(flags&V_FLAG)?1:0;
 40.1704 +                        if (temp!=temp2)  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1705 +                        cycles -= 3;
 40.1706 +                        break;
 40.1707 +                        case 0x7D: /*JNL*/
 40.1708 +                        offset=(int8_t)getbytef();
 40.1709 +                        temp=(flags&N_FLAG)?1:0;
 40.1710 +                        temp2=(flags&V_FLAG)?1:0;
 40.1711 +                        if (temp==temp2)  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1712 +                        cycles -= 3;
 40.1713 +                        break;
 40.1714 +                        case 0x7E: /*JLE*/
 40.1715 +                        offset=(int8_t)getbytef();
 40.1716 +                        temp=(flags&N_FLAG)?1:0;
 40.1717 +                        temp2=(flags&V_FLAG)?1:0;
 40.1718 +                        if ((flags&Z_FLAG) || (temp!=temp2))  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1719 +                        cycles -= 3;
 40.1720 +                        break;
 40.1721 +                        case 0x7F: /*JNLE*/
 40.1722 +                        offset=(int8_t)getbytef();
 40.1723 +                        temp=(flags&N_FLAG)?1:0;
 40.1724 +                        temp2=(flags&V_FLAG)?1:0;
 40.1725 +                        if (!((flags&Z_FLAG) || (temp!=temp2)))  { pc += offset; cycles -= 4; cycles -= 2; }
 40.1726 +                        cycles -= 3;
 40.1727 +                        break;
 40.1728 +
 40.1729 +
 40.1730 +                        case 0x80: 
 40.1731 +                        case 0x82:
 40.1732 +                        fetchea();
 40.1733 +                        temp=geteab();                  if (abrt) break;
 40.1734 +                        temp2=readmemb(cs,pc); pc++;    if (abrt) break;
 40.1735 +                        switch (rmdat&0x38)
 40.1736 +                        {
 40.1737 +                                case 0x00: /*ADD b,#8*/
 40.1738 +                                seteab(temp+temp2);             if (abrt) break;
 40.1739 +                                setadd8(temp,temp2);
 40.1740 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1741 +                                break;
 40.1742 +                                case 0x08: /*OR b,#8*/
 40.1743 +                                temp|=temp2;
 40.1744 +                                seteab(temp);                   if (abrt) break;
 40.1745 +                                setznp8(temp);
 40.1746 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1747 +                                break;
 40.1748 +                                case 0x10: /*ADC b,#8*/
 40.1749 +                                seteab(temp+temp2+tempc);       if (abrt) break;
 40.1750 +                                setadc8(temp,temp2);
 40.1751 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1752 +                                break;
 40.1753 +                                case 0x18: /*SBB b,#8*/
 40.1754 +                                seteab(temp-(temp2+tempc));     if (abrt) break;
 40.1755 +                                setsbc8(temp,temp2);
 40.1756 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1757 +                                break;
 40.1758 +                                case 0x20: /*AND b,#8*/
 40.1759 +                                temp&=temp2;
 40.1760 +                                seteab(temp);                   if (abrt) break;
 40.1761 +                                setznp8(temp);
 40.1762 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1763 +                                break;
 40.1764 +                                case 0x28: /*SUB b,#8*/
 40.1765 +                                seteab(temp-temp2);             if (abrt) break;
 40.1766 +                                setsub8(temp,temp2);
 40.1767 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1768 +                                break;
 40.1769 +                                case 0x30: /*XOR b,#8*/
 40.1770 +                                temp^=temp2;
 40.1771 +                                seteab(temp);                   if (abrt) break;
 40.1772 +                                setznp8(temp);
 40.1773 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1774 +                                break;
 40.1775 +                                case 0x38: /*CMP b,#8*/
 40.1776 +                                setsub8(temp,temp2);
 40.1777 +                                cycles -= (mod == 3) ? 3 : 6;
 40.1778 +                                break;
 40.1779 +
 40.1780 +//                                default:
 40.1781 +//                                pclog("Bad 80 opcode %02X\n",rmdat&0x38);
 40.1782 +//                                dumpregs();
 40.1783 +//                                exit(-1);
 40.1784 +                        }
 40.1785 +                        break;
 40.1786 +
 40.1787 +                        case 0x81: 
 40.1788 +                        fetchea();
 40.1789 +                        tempw=geteaw();         if (abrt) break;
 40.1790 +                        tempw2=getword();       if (abrt) break;
 40.1791 +                        switch (rmdat&0x38)
 40.1792 +                        {
 40.1793 +                                case 0x00: /*ADD w,#16*/
 40.1794 +                                seteaw(tempw+tempw2);   if (abrt) break;
 40.1795 +                                setadd16(tempw,tempw2);
 40.1796 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1797 +                                break;
 40.1798 +                                case 0x08: /*OR w,#16*/
 40.1799 +                                tempw|=tempw2;
 40.1800 +                                seteaw(tempw);          if (abrt) break;
 40.1801 +                                setznp16(tempw);
 40.1802 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1803 +                                break;
 40.1804 +                                case 0x10: /*ADC w,#16*/
 40.1805 +                                seteaw(tempw+tempw2+tempc); if (abrt) break;
 40.1806 +                                setadc16(tempw,tempw2);
 40.1807 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1808 +                                break;
 40.1809 +                                case 0x20: /*AND w,#16*/
 40.1810 +                                tempw&=tempw2;
 40.1811 +                                seteaw(tempw);          if (abrt) break;
 40.1812 +                                setznp16(tempw);
 40.1813 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1814 +                                break;
 40.1815 +                                case 0x18: /*SBB w,#16*/
 40.1816 +                                seteaw(tempw-(tempw2+tempc));   if (abrt) break;
 40.1817 +                                setsbc16(tempw,tempw2);
 40.1818 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1819 +                                break;
 40.1820 +                                case 0x28: /*SUB w,#16*/
 40.1821 +                                seteaw(tempw-tempw2);           if (abrt) break;
 40.1822 +                                setsub16(tempw,tempw2);
 40.1823 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1824 +                                break;
 40.1825 +                                case 0x30: /*XOR w,#16*/
 40.1826 +                                tempw^=tempw2;
 40.1827 +                                seteaw(tempw);                  if (abrt) break;
 40.1828 +                                setznp16(tempw);
 40.1829 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1830 +                                break;
 40.1831 +                                case 0x38: /*CMP w,#16*/
 40.1832 +//                                pclog("CMP %04X %04X\n", tempw, tempw2);
 40.1833 +                                setsub16(tempw,tempw2);
 40.1834 +                                cycles -= (mod == 3) ? 3 : 6;
 40.1835 +                                break;
 40.1836 +                        }
 40.1837 +                        break;
 40.1838 +
 40.1839 +                        case 0x83:
 40.1840 +                        fetchea();
 40.1841 +                        tempw=geteaw();                 if (abrt) break;
 40.1842 +                        tempw2=readmemb(cs,pc); pc++;   if (abrt) break;
 40.1843 +                        if (tempw2&0x80) tempw2|=0xFF00;
 40.1844 +                        switch (rmdat&0x38)
 40.1845 +                        {
 40.1846 +                                case 0x00: /*ADD w,#8*/
 40.1847 +                                seteaw(tempw+tempw2);           if (abrt) break;
 40.1848 +                                setadd16(tempw,tempw2);
 40.1849 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1850 +                                break;
 40.1851 +                                case 0x08: /*OR w,#8*/
 40.1852 +                                tempw|=tempw2;
 40.1853 +                                seteaw(tempw);                  if (abrt) break;
 40.1854 +                                setznp16(tempw);
 40.1855 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1856 +                                break;
 40.1857 +                                case 0x10: /*ADC w,#8*/
 40.1858 +                                seteaw(tempw+tempw2+tempc);     if (abrt) break;
 40.1859 +                                setadc16(tempw,tempw2);
 40.1860 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1861 +                                break;
 40.1862 +                                case 0x18: /*SBB w,#8*/
 40.1863 +                                seteaw(tempw-(tempw2+tempc));   if (abrt) break;
 40.1864 +                                setsbc16(tempw,tempw2);
 40.1865 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1866 +                                break;
 40.1867 +                                case 0x20: /*AND w,#8*/
 40.1868 +                                tempw&=tempw2;
 40.1869 +                                seteaw(tempw);                  if (abrt) break;
 40.1870 +                                setznp16(tempw);
 40.1871 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1872 +                                break;
 40.1873 +                                case 0x28: /*SUB w,#8*/
 40.1874 +                                seteaw(tempw-tempw2);           if (abrt) break;
 40.1875 +                                setsub16(tempw,tempw2);
 40.1876 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1877 +                                break;
 40.1878 +                                case 0x30: /*XOR w,#8*/
 40.1879 +                                tempw^=tempw2;
 40.1880 +                                seteaw(tempw);                  if (abrt) break;
 40.1881 +                                setznp16(tempw);
 40.1882 +                                cycles -= (mod == 3) ? 3 : 7;
 40.1883 +                                break;
 40.1884 +                                case 0x38: /*CMP w,#8*/
 40.1885 +                                setsub16(tempw,tempw2);
 40.1886 +                                cycles -= (mod == 3) ? 3 : 6;
 40.1887 +                                break;
 40.1888 +
 40.1889 +//                                default:
 40.1890 +//                                pclog("Bad 83 opcode %02X\n",rmdat&0x38);
 40.1891 +//                                dumpregs();
 40.1892 +//                                exit(-1);
 40.1893 +                        }
 40.1894 +                        break;
 40.1895 +
 40.1896 +                        case 0x84: /*TEST b,reg*/
 40.1897 +                        fetchea();
 40.1898 +                        temp=geteab();          if (abrt) break;
 40.1899 +                        temp2=getr8(reg);
 40.1900 +                        setznp8(temp&temp2);
 40.1901 +                        cycles -= (mod == 3) ? 2 : 6;
 40.1902 +                        break;
 40.1903 +                        case 0x85: /*TEST w,reg*/
 40.1904 +                        fetchea();
 40.1905 +                        tempw=geteaw();         if (abrt) break;
 40.1906 +                        tempw2=regs[reg].w;
 40.1907 +                        setznp16(tempw&tempw2);
 40.1908 +                        cycles -= (mod == 3) ? 2 : 6;
 40.1909 +                        break;
 40.1910 +                        case 0x86: /*XCHG b,reg*/
 40.1911 +                        fetchea();
 40.1912 +                        temp=geteab();          if (abrt) break;
 40.1913 +                        seteab(getr8(reg));     if (abrt) break;
 40.1914 +                        setr8(reg,temp);
 40.1915 +                        cycles -= (mod == 3) ? 3 : 5;
 40.1916 +                        break;
 40.1917 +                        case 0x87: /*XCHG w,reg*/
 40.1918 +                        fetchea();
 40.1919 +                        tempw=geteaw();         if (abrt) break;
 40.1920 +                        seteaw(regs[reg].w);    if (abrt) break;
 40.1921 +                        regs[reg].w=tempw;
 40.1922 +                        cycles -= (mod == 3) ? 3 : 5;
 40.1923 +                        break;
 40.1924 +
 40.1925 +                        case 0x88: /*MOV b,reg*/
 40.1926 +                        fetchea();
 40.1927 +                        seteab(getr8(reg));
 40.1928 +                        cycles -= (mod == 3) ? 2 : 3;
 40.1929 +                        break;
 40.1930 +                        case 0x89: /*MOV w,reg*/
 40.1931 +                        fetchea();
 40.1932 +                        seteaw(regs[reg].w);
 40.1933 +                        cycles -= (mod == 3) ? 2 : 3;
 40.1934 +                        break;
 40.1935 +                        case 0x8A: /*MOV reg,b*/
 40.1936 +                        fetchea();
 40.1937 +                        temp=geteab();          if (abrt) break;
 40.1938 +                        setr8(reg,temp);
 40.1939 +                        cycles -= (mod == 3) ? 5 : 3;
 40.1940 +                        break;
 40.1941 +                        case 0x8B: /*MOV reg,w*/
 40.1942 +                        fetchea();
 40.1943 +                        tempw=geteaw();         if (abrt) break;
 40.1944 +                        regs[reg].w=tempw;
 40.1945 +                        cycles -= (mod == 3) ? 5 : 3;
 40.1946 +                        break;
 40.1947 +
 40.1948 +                        case 0x8C: /*MOV w,sreg*/
 40.1949 +                        fetchea();
 40.1950 +                        switch (rmdat&0x38)
 40.1951 +                        {
 40.1952 +                                case 0x00: /*ES*/
 40.1953 +                                seteaw(ES);
 40.1954 +                                break;
 40.1955 +                                case 0x08: /*CS*/
 40.1956 +                                seteaw(CS);
 40.1957 +                                break;
 40.1958 +                                case 0x18: /*DS*/
 40.1959 +                                if (ssegs) ds=oldds;
 40.1960 +                                seteaw(DS);
 40.1961 +                                break;
 40.1962 +                                case 0x10: /*SS*/
 40.1963 +                                if (ssegs) ss=oldss;
 40.1964 +                                seteaw(SS);
 40.1965 +                                break;
 40.1966 +                        }
 40.1967 +                        cycles -= (mod == 3) ? 2 : 3;
 40.1968 +                        break;
 40.1969 +
 40.1970 +                        case 0x8D: /*LEA*/
 40.1971 +                        fetchea();
 40.1972 +                        regs[reg].w=eaaddr;
 40.1973 +                        cycles -= 3;
 40.1974 +                        break;
 40.1975 +
 40.1976 +                        case 0x8E: /*MOV sreg,w*/
 40.1977 +                        fetchea();
 40.1978 +                        switch (rmdat&0x38)
 40.1979 +                        {
 40.1980 +                                case 0x00: /*ES*/
 40.1981 +                                tempw=geteaw();         if (abrt) break;
 40.1982 +                                loadseg(tempw,&_es);
 40.1983 +                                break;
 40.1984 +                                case 0x18: /*DS*/
 40.1985 +                                tempw=geteaw();         if (abrt) break;
 40.1986 +                                loadseg(tempw,&_ds);
 40.1987 +                                if (ssegs) oldds=ds;
 40.1988 +                                break;
 40.1989 +                                case 0x10: /*SS*/
 40.1990 +//                                if (output==3) pclog("geteaw\n");
 40.1991 +                                tempw=geteaw();         if (abrt) break;
 40.1992 +//                                if (output==3) pclog("loadseg\n");
 40.1993 +                                loadseg(tempw,&_ss);
 40.1994 +//                                if (output==3) pclog("done\n");
 40.1995 +                                if (ssegs) oldss=ss;
 40.1996 +                                skipnextprint=1;
 40.1997 +				noint=1;
 40.1998 +                                break;
 40.1999 +                        }
 40.2000 +                        if (msw & 1) cycles -= (mod == 3) ? 17 : 19;
 40.2001 +                        else         cycles -= (mod == 3) ?  2 :  5;
 40.2002 +                        break;
 40.2003 +
 40.2004 +                        case 0x8F: /*POPW*/
 40.2005 +                        if (ssegs) templ2=oldss;
 40.2006 +                        else       templ2=ss;
 40.2007 +                        tempw=readmemw(templ2,SP);      if (abrt) break;
 40.2008 +                        SP+=2;
 40.2009 +                        fetchea();
 40.2010 +                        if (ssegs) ss=oldss;
 40.2011 +                        seteaw(tempw);
 40.2012 +                        if (abrt) SP-=2;
 40.2013 +                        cycles -= 5;
 40.2014 +                        break;
 40.2015 +
 40.2016 +                        case 0x90: /*NOP*/
 40.2017 +                        cycles -= 3;
 40.2018 +                        break;
 40.2019 +
 40.2020 +                        case 0x91: case 0x92: case 0x93: /*XCHG AX*/
 40.2021 +                        case 0x94: case 0x95: case 0x96: case 0x97:
 40.2022 +                        tempw=AX;
 40.2023 +                        AX=regs[opcode&7].w;
 40.2024 +                        regs[opcode&7].w=tempw;
 40.2025 +                        cycles -= 3;
 40.2026 +                        break;
 40.2027 +
 40.2028 +                        case 0x98: /*CBW*/
 40.2029 +                        AH=(AL&0x80)?0xFF:0;
 40.2030 +                        cycles -= 2;
 40.2031 +                        break;
 40.2032 +                        case 0x99: /*CWD*/
 40.2033 +                        DX=(AX&0x8000)?0xFFFF:0;
 40.2034 +                        cycles -= 2;
 40.2035 +                        break;
 40.2036 +                        case 0x9A: /*CALL FAR*/
 40.2037 +                        tempw=getword();
 40.2038 +                        tempw2=getword();       if (abrt) break;
 40.2039 +                        tempw3 = CS;
 40.2040 +                        templ2 = pc;
 40.2041 +                        if (ssegs) ss=oldss;
 40.2042 +                        oxpc=pc;
 40.2043 +                        pc=tempw;
 40.2044 +                        optype=CALL;
 40.2045 +                        if (msw&1) loadcscall(tempw2);
 40.2046 +                        else       loadcs(tempw2);
 40.2047 +                        optype=0;
 40.2048 +                        if (abrt) break;
 40.2049 +                        oldss=ss;
 40.2050 +                        writememw(ss,(SP-2)&0xFFFF,tempw3);
 40.2051 +                        writememw(ss,(SP-4)&0xFFFF,templ2);     if (abrt) break;
 40.2052 +                        SP-=4;
 40.2053 +                        cycles -= (msw & 1) ? 26 : 13;
 40.2054 +                        break;
 40.2055 +                        case 0x9B: /*WAIT*/
 40.2056 +                        cycles -= 3;
 40.2057 +                        break;
 40.2058 +                        case 0x9C: /*PUSHF*/
 40.2059 +                        if (ssegs) ss=oldss;
 40.2060 +                        if (msw & 1) { writememw(ss, ((SP-2)&0xFFFF), flags & 0x7fff); }
 40.2061 +                        else         { writememw(ss, ((SP-2)&0xFFFF), flags & 0x0fff); }   
 40.2062 +                        if (abrt) break;
 40.2063 +                        SP-=2;
 40.2064 +                        cycles -= 3;
 40.2065 +                        break;
 40.2066 +                        case 0x9D: /*POPF*/
 40.2067 +                        if (ssegs) ss=oldss;
 40.2068 +                        tempw=readmemw(ss,SP);                  if (abrt) break;
 40.2069 +                        SP+=2;
 40.2070 +                        if (!(CPL) || !(msw&1)) flags=(tempw&0xFFD5)|2;
 40.2071 +                        else if (IOPLp) flags=(flags&0x3000)|(tempw&0x4FD5)|2;
 40.2072 +                        else            flags=(flags&0x7200)|(tempw&0x0DD5)|2;
 40.2073 +                        pclog("POPF %04X %04X  %04X:%04X\n", tempw, flags, CS, pc);
 40.2074 +                        cycles -= 5;
 40.2075 +                        break;
 40.2076 +                        case 0x9E: /*SAHF*/
 40.2077 +                        flags=(flags&0xFF00)|(AH&0xD5)|2;
 40.2078 +                        cycles -= 2;
 40.2079 +                        break;
 40.2080 +                        case 0x9F: /*LAHF*/
 40.2081 +                        AH=flags&0xFF;
 40.2082 +                        cycles -= 2;
 40.2083 +                        break;
 40.2084 +
 40.2085 +                        case 0xA0: /*MOV AL,(w)*/
 40.2086 +                        addr=getword(); if (abrt) break;
 40.2087 +                        temp=readmemb(ds,addr);         if (abrt) break;
 40.2088 +                        AL=temp;
 40.2089 +                        cycles -= 5;
 40.2090 +                        break;
 40.2091 +                        case 0xA1: /*MOV AX,(w)*/
 40.2092 +                        addr=getword(); if (abrt) break;
 40.2093 +                        tempw=readmemw(ds,addr);        if (abrt) break;
 40.2094 +                        AX=tempw;
 40.2095 +                        cycles -= 5;
 40.2096 +                        break;
 40.2097 +                        case 0xA2: /*MOV (w),AL*/
 40.2098 +                        addr=getword(); if (abrt) break;
 40.2099 +                        writememb(ds,addr,AL);
 40.2100 +                        cycles -= 3;
 40.2101 +                        break;
 40.2102 +                        case 0xA3: /*MOV (w),AX*/
 40.2103 +                        addr=getword(); if (abrt) break;
 40.2104 +                        writememw(ds,addr,AX);
 40.2105 +                        cycles -= 3;
 40.2106 +                        break;
 40.2107 +
 40.2108 +                        case 0xA4: /*MOVSB*/
 40.2109 +                        temp=readmemb(ds,SI);  if (abrt) break;
 40.2110 +                        writememb(es,DI,temp); if (abrt) break;
 40.2111 +                        if (flags&D_FLAG) { DI--; SI--; }
 40.2112 +                        else              { DI++; SI++; }
 40.2113 +                        cycles -= 5;
 40.2114 +                        break;
 40.2115 +                        case 0xA5: /*MOVSW*/
 40.2116 +                        tempw=readmemw(ds,SI);  if (abrt) break;
 40.2117 +                        writememw(es,DI,tempw); if (abrt) break;
 40.2118 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
 40.2119 +                        else              { DI+=2; SI+=2; }
 40.2120 +                        cycles -= 5;
 40.2121 +                        break;
 40.2122 +                        case 0xA6: /*CMPSB*/
 40.2123 +                        temp =readmemb(ds,SI);
 40.2124 +                        temp2=readmemb(es,DI);
 40.2125 +                        if (abrt) break;
 40.2126 +                        setsub8(temp,temp2);
 40.2127 +                        if (flags&D_FLAG) { DI--; SI--; }
 40.2128 +                        else              { DI++; SI++; }
 40.2129 +                        cycles -= 8;
 40.2130 +                        break;
 40.2131 +                        case 0xA7: /*CMPSW*/
 40.2132 +                        tempw =readmemw(ds,SI);
 40.2133 +                        tempw2=readmemw(es,DI);
 40.2134 +                        if (abrt) break;
 40.2135 +                        setsub16(tempw,tempw2);
 40.2136 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
 40.2137 +                        else              { DI+=2; SI+=2; }
 40.2138 +                        cycles -= 8;
 40.2139 +                        break;
 40.2140 +                        case 0xA8: /*TEST AL,#8*/
 40.2141 +                        temp=getbytef();
 40.2142 +                        setznp8(AL&temp);
 40.2143 +                        cycles -= 3;
 40.2144 +                        break;
 40.2145 +                        case 0xA9: /*TEST AX,#16*/
 40.2146 +                        tempw=getwordf();
 40.2147 +                        setznp16(AX&tempw);
 40.2148 +                        cycles -= 3;
 40.2149 +                        break;
 40.2150 +                        case 0xAA: /*STOSB*/
 40.2151 +                        writememb(es,DI,AL);    if (abrt) break;
 40.2152 +                        if (flags&D_FLAG) DI--;
 40.2153 +                        else              DI++;
 40.2154 +                        cycles -= 3;
 40.2155 +                        break;
 40.2156 +                        case 0xAB: /*STOSW*/
 40.2157 +                        writememw(es,DI,AX);    if (abrt) break;
 40.2158 +                        if (flags&D_FLAG) DI-=2;
 40.2159 +                        else              DI+=2;
 40.2160 +                        cycles -= 3;
 40.2161 +                        break;
 40.2162 +                        case 0xAC: /*LODSB*/
 40.2163 +                        temp=readmemb(ds,SI);
 40.2164 +                        if (abrt) break;
 40.2165 +                        AL=temp;
 40.2166 +                        if (flags&D_FLAG) SI--;
 40.2167 +                        else              SI++;
 40.2168 +                        cycles -= 5;
 40.2169 +                        break;
 40.2170 +                        case 0xAD: /*LODSW*/
 40.2171 +                        tempw=readmemw(ds,SI);
 40.2172 +                        if (abrt) break;
 40.2173 +                        AX=tempw;
 40.2174 +//                        if (output) pclog("Load from %05X:%04X\n",ds,SI);
 40.2175 +                        if (flags&D_FLAG) SI-=2;
 40.2176 +                        else              SI+=2;
 40.2177 +                        cycles -= 5;
 40.2178 +                        break;
 40.2179 +                        case 0xAE: /*SCASB*/
 40.2180 +                        temp=readmemb(es,DI);
 40.2181 +                        if (abrt) break;
 40.2182 +                        setsub8(AL,temp);
 40.2183 +                        if (flags&D_FLAG) DI--;
 40.2184 +                        else              DI++;
 40.2185 +                        cycles -= 7;
 40.2186 +                        break;
 40.2187 +                        case 0xAF: /*SCASW*/
 40.2188 +                        tempw=readmemw(es,DI);
 40.2189 +                        if (abrt) break;
 40.2190 +                        setsub16(AX,tempw);
 40.2191 +                        if (flags&D_FLAG) DI-=2;
 40.2192 +                        else              DI+=2;
 40.2193 +                        cycles -= 7;
 40.2194 +                        break;
 40.2195 +
 40.2196 +                        case 0xB0: /*MOV AL,#8*/
 40.2197 +                        AL=getbytef();
 40.2198 +                        cycles -= 2;
 40.2199 +                        break;
 40.2200 +                        case 0xB1: /*MOV CL,#8*/
 40.2201 +                        CL=getbytef();
 40.2202 +                        cycles -= 2;
 40.2203 +                        break;
 40.2204 +                        case 0xB2: /*MOV DL,#8*/
 40.2205 +                        DL=getbytef();
 40.2206 +                        cycles -= 2;
 40.2207 +                        break;
 40.2208 +                        case 0xB3: /*MOV BL,#8*/
 40.2209 +                        BL=getbytef();
 40.2210 +                        cycles -= 2;
 40.2211 +                        break;
 40.2212 +                        case 0xB4: /*MOV AH,#8*/
 40.2213 +                        AH=getbytef();
 40.2214 +                        cycles -= 2;
 40.2215 +                        break;
 40.2216 +                        case 0xB5: /*MOV CH,#8*/
 40.2217 +                        CH=getbytef();
 40.2218 +                        cycles -= 2;
 40.2219 +                        break;
 40.2220 +                        case 0xB6: /*MOV DH,#8*/
 40.2221 +                        DH=getbytef();
 40.2222 +                        cycles -= 2;
 40.2223 +                        break;
 40.2224 +                        case 0xB7: /*MOV BH,#8*/
 40.2225 +                        BH=getbytef();
 40.2226 +                        cycles -= 2;
 40.2227 +                        break;
 40.2228 +                        case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/
 40.2229 +                        case 0xBC: case 0xBD: case 0xBE: case 0xBF:
 40.2230 +                        regs[opcode&7].w=getwordf();
 40.2231 +                        cycles -= 2;
 40.2232 +                        break;
 40.2233 +
 40.2234 +                        case 0xC0:
 40.2235 +                        fetchea();
 40.2236 +                        c=readmemb(cs,pc); pc++;
 40.2237 +                        temp=geteab();          if (abrt) break;
 40.2238 +                        c&=31;
 40.2239 +                        if (!c) break;
 40.2240 +                        cycles -= c;                        
 40.2241 +                        switch (rmdat&0x38)
 40.2242 +                        {
 40.2243 +                                case 0x00: /*ROL b,CL*/
 40.2244 +                                while (c>0)
 40.2245 +                                {
 40.2246 +                                        temp2=(temp&0x80)?1:0;
 40.2247 +                                        temp=(temp<<1)|temp2;
 40.2248 +                                        c--;
 40.2249 +                                }
 40.2250 +                                seteab(temp);   if (abrt) break;
 40.2251 +                                flags&=~(C_FLAG|V_FLAG);
 40.2252 +                                if (temp2) flags|=C_FLAG;
 40.2253 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2254 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2255 +                                break;
 40.2256 +                                case 0x08: /*ROR b,CL*/
 40.2257 +                                while (c>0)
 40.2258 +                                {
 40.2259 +                                        temp2=temp&1;
 40.2260 +                                        temp>>=1;
 40.2261 +                                        if (temp2) temp|=0x80;
 40.2262 +                                        c--;
 40.2263 +                                }
 40.2264 +                                seteab(temp);   if (abrt) break;
 40.2265 +                                flags&=~(C_FLAG|V_FLAG);
 40.2266 +                                if (temp2) flags|=C_FLAG;
 40.2267 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2268 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2269 +                                break;
 40.2270 +                                case 0x10: /*RCL b,CL*/
 40.2271 +                                temp2=flags&C_FLAG;
 40.2272 +                                while (c>0)
 40.2273 +                                {
 40.2274 +                                        tempc=(temp2)?1:0;
 40.2275 +                                        temp2=temp&0x80;
 40.2276 +                                        temp=(temp<<1)|tempc;
 40.2277 +                                        c--;
 40.2278 +                                        if (is486) cycles--;
 40.2279 +                                }
 40.2280 +                                seteab(temp);   if (abrt) break;
 40.2281 +                                flags&=~(C_FLAG|V_FLAG);
 40.2282 +                                if (temp2) flags|=C_FLAG;
 40.2283 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2284 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2285 +                                break;
 40.2286 +                                case 0x18: /*RCR b,CL*/
 40.2287 +                                temp2=flags&C_FLAG;
 40.2288 +                                while (c>0)
 40.2289 +                                {
 40.2290 +                                        tempc=(temp2)?0x80:0;
 40.2291 +                                        temp2=temp&1;
 40.2292 +                                        temp=(temp>>1)|tempc;
 40.2293 +                                        c--;
 40.2294 +                                        if (is486) cycles--;
 40.2295 +                                }
 40.2296 +                                seteab(temp);   if (abrt) break;
 40.2297 +                                flags&=~(C_FLAG|V_FLAG);
 40.2298 +                                if (temp2) flags|=C_FLAG;
 40.2299 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2300 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2301 +                                break;
 40.2302 +                                case 0x20: case 0x30: /*SHL b,CL*/
 40.2303 +                                seteab(temp<<c);        if (abrt) break;
 40.2304 +                                setznp8(temp<<c);
 40.2305 +                                if ((temp<<(c-1))&0x80) flags|=C_FLAG;
 40.2306 +                                if (((temp<<c)^(temp<<(c-1)))&0x80) flags|=V_FLAG;
 40.2307 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2308 +                                break;
 40.2309 +                                case 0x28: /*SHR b,CL*/
 40.2310 +                                seteab(temp>>c);        if (abrt) break;
 40.2311 +                                setznp8(temp>>c);
 40.2312 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
 40.2313 +                                if (c==1 && temp&0x80) flags|=V_FLAG;
 40.2314 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2315 +                                break;
 40.2316 +                                case 0x38: /*SAR b,CL*/
 40.2317 +                                tempc=((temp>>(c-1))&1);
 40.2318 +                                while (c>0)
 40.2319 +                                {
 40.2320 +                                        temp>>=1;
 40.2321 +                                        if (temp&0x40) temp|=0x80;
 40.2322 +                                        c--;
 40.2323 +                                }
 40.2324 +                                seteab(temp);   if (abrt) break;
 40.2325 +                                setznp8(temp);
 40.2326 +                                if (tempc) flags|=C_FLAG;
 40.2327 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2328 +                                break;
 40.2329 +
 40.2330 +//                                default:
 40.2331 +//                                pclog("Bad C0 opcode %02X\n",rmdat&0x38);
 40.2332 +//                                dumpregs();
 40.2333 +//                                exit(-1);
 40.2334 +                        }
 40.2335 +                        break;
 40.2336 +
 40.2337 +                        case 0xC1:
 40.2338 +                        fetchea();
 40.2339 +                        c=readmemb(cs,pc)&31; pc++;
 40.2340 +                        tempw=geteaw();         if (abrt) break;
 40.2341 +                        if (!c) break;
 40.2342 +                        cycles -= c;
 40.2343 +                        switch (rmdat&0x38)
 40.2344 +                        {
 40.2345 +                                case 0x00: /*ROL w,CL*/
 40.2346 +                                while (c>0)
 40.2347 +                                {
 40.2348 +                                        temp=(tempw&0x8000)?1:0;
 40.2349 +                                        tempw=(tempw<<1)|temp;
 40.2350 +                                        c--;
 40.2351 +                                }
 40.2352 +                                seteaw(tempw);  if (abrt) break;
 40.2353 +                                flags&=~(C_FLAG|V_FLAG);
 40.2354 +                                if (temp) flags|=C_FLAG;
 40.2355 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2356 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2357 +                                break;
 40.2358 +                                case 0x08: /*ROR w,CL*/
 40.2359 +                                while (c>0)
 40.2360 +                                {
 40.2361 +                                        tempw2=(tempw&1)?0x8000:0;
 40.2362 +                                        tempw=(tempw>>1)|tempw2;
 40.2363 +                                        c--;
 40.2364 +                                }
 40.2365 +                                seteaw(tempw);  if (abrt) break;
 40.2366 +                                flags&=~(C_FLAG|V_FLAG);
 40.2367 +                                if (tempw2) flags|=C_FLAG;
 40.2368 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2369 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2370 +                                break;
 40.2371 +                                case 0x10: /*RCL w,CL*/
 40.2372 +                                temp2=flags&C_FLAG;
 40.2373 +                                while (c>0)
 40.2374 +                                {
 40.2375 +                                        tempc=(temp2)?1:0;
 40.2376 +                                        temp2=(tempw>>15);
 40.2377 +                                        tempw=(tempw<<1)|tempc;
 40.2378 +                                        c--;
 40.2379 +                                        if (is486) cycles--;
 40.2380 +                                }
 40.2381 +                                seteaw(tempw);  if (abrt) break;
 40.2382 +                                flags&=~(C_FLAG|V_FLAG);
 40.2383 +                                if (temp2) flags|=C_FLAG;
 40.2384 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2385 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2386 +                                break;
 40.2387 +                                case 0x18: /*RCR w,CL*/
 40.2388 +                                temp2=flags&C_FLAG;
 40.2389 +                                while (c>0)
 40.2390 +                                {
 40.2391 +                                        tempc=(temp2)?0x8000:0;
 40.2392 +                                        temp2=tempw&1;
 40.2393 +                                        tempw=(tempw>>1)|tempc;
 40.2394 +                                        c--;
 40.2395 +                                        if (is486) cycles--;
 40.2396 +                                }
 40.2397 +                                seteaw(tempw);  if (abrt) break;
 40.2398 +                                flags&=~(C_FLAG|V_FLAG);
 40.2399 +                                if (temp2) flags|=C_FLAG;
 40.2400 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2401 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2402 +                                break;
 40.2403 +
 40.2404 +                                case 0x20: case 0x30: /*SHL w,CL*/
 40.2405 +                                seteaw(tempw<<c); if (abrt) break;
 40.2406 +                                setznp16(tempw<<c);
 40.2407 +                                if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
 40.2408 +                                if (((tempw<<c)^(tempw<<(c-1)))&0x8000) flags|=V_FLAG;
 40.2409 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2410 +                                break;
 40.2411 +
 40.2412 +                                case 0x28:            /*SHR w,CL*/
 40.2413 +                                seteaw(tempw>>c); if (abrt) break;
 40.2414 +                                setznp16(tempw>>c);
 40.2415 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
 40.2416 +                                if (c==1 && tempw&0x8000) flags|=V_FLAG;
 40.2417 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2418 +                                break;
 40.2419 +
 40.2420 +                                case 0x38:            /*SAR w,CL*/
 40.2421 +                                tempw2=tempw&0x8000;
 40.2422 +                                tempc=(tempw>>(c-1))&1;
 40.2423 +                                while (c>0)
 40.2424 +                                {
 40.2425 +                                        tempw=(tempw>>1)|tempw2;
 40.2426 +                                        c--;
 40.2427 +                                }
 40.2428 +                                seteaw(tempw);  if (abrt) break;
 40.2429 +                                setznp16(tempw);
 40.2430 +                                if (tempc) flags|=C_FLAG;
 40.2431 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2432 +                                break;
 40.2433 +
 40.2434 +//                                default:
 40.2435 +//                                pclog("Bad C1 opcode %02X\n",rmdat&0x38);
 40.2436 +//                                dumpregs();
 40.2437 +//                                exit(-1);
 40.2438 +                        }
 40.2439 +                        break;
 40.2440 +
 40.2441 +                        case 0xC2: /*RET*/
 40.2442 +                        tempw=getword();
 40.2443 +                        if (ssegs) ss=oldss;
 40.2444 +                        tempw2=readmemw(ss,SP); if (abrt) break;
 40.2445 +                        SP+=2+tempw;
 40.2446 +                        pc=tempw2;
 40.2447 +                        cycles -= 11;
 40.2448 +                        break;
 40.2449 +                        case 0xC3: /*RET*/
 40.2450 +                        if (ssegs) ss=oldss;
 40.2451 +                        tempw=readmemw(ss,SP);  if (abrt) break;
 40.2452 +                        SP+=2;
 40.2453 +                        pc=tempw;
 40.2454 +                        cycles -= 11;
 40.2455 +                        break;
 40.2456 +                        case 0xC4: /*LES*/
 40.2457 +                        fetchea();
 40.2458 +                        tempw2=readmemw(easeg,eaaddr);
 40.2459 +                        tempw=readmemw(easeg,eaaddr+2); if (abrt) break;
 40.2460 +                        loadseg(tempw,&_es);            if (abrt) break;
 40.2461 +                        regs[reg].w=tempw2;
 40.2462 +                        cycles -= 7;
 40.2463 +                        break;
 40.2464 +                        case 0xC5: /*LDS*/
 40.2465 +                        fetchea();
 40.2466 +                        tempw2=readmemw(easeg,eaaddr);
 40.2467 +                        tempw=readmemw(easeg,eaaddr+2); if (abrt) break;
 40.2468 +                        loadseg(tempw,&_ds);            if (abrt) break;
 40.2469 +                        if (ssegs) oldds=ds;
 40.2470 +                        regs[reg].w=tempw2;
 40.2471 +                        cycles -= 7;
 40.2472 +                        break;
 40.2473 +                        case 0xC6: /*MOV b,#8*/
 40.2474 +                        fetchea();
 40.2475 +                        temp=readmemb(cs,pc); pc++;     if (abrt) break;
 40.2476 +                        seteab(temp);
 40.2477 +                        cycles -= (mod == 3) ? 2 : 3;
 40.2478 +                        break;
 40.2479 +                        case 0xC7: /*MOV w,#16*/
 40.2480 +                        fetchea();
 40.2481 +                        tempw=getword();                if (abrt) break;
 40.2482 +                        seteaw(tempw);
 40.2483 +                        cycles -= (mod == 3) ? 2 : 3;
 40.2484 +                        break;
 40.2485 +                        case 0xC8: /*ENTER*/
 40.2486 +                        tempw2=getword();
 40.2487 +                        tempi=readmemb(cs,pc); pc++;
 40.2488 +                        templ=BP;
 40.2489 +                        writememw(ss,((SP-2)&0xFFFF),BP); if (abrt) break; 
 40.2490 +                        SP-=2;
 40.2491 +                        templ2=SP;
 40.2492 +                        if (tempi>0)
 40.2493 +                        {
 40.2494 +                                while (--tempi)
 40.2495 +                                {
 40.2496 +                                        BP-=2;
 40.2497 +                                        tempw=readmemw(ss,BP);
 40.2498 +                                        if (abrt) { SP=templ2; BP=templ; break; }
 40.2499 +                                        writememw(ss,((SP-2)&0xFFFF),tempw); SP-=2;
 40.2500 +                                        if (abrt) { SP=templ2; BP=templ; break; }
 40.2501 +                                        cycles-=(is486)?3:4;
 40.2502 +                                }
 40.2503 +                                writememw(ss,((SP-2)&0xFFFF),templ2); SP-=2;
 40.2504 +                                if (abrt) { SP=templ2; BP=templ; break; }
 40.2505 +                                cycles -= 4;
 40.2506 +                        }
 40.2507 +                        BP = templ2;
 40.2508 +                        SP-=tempw2;
 40.2509 +                        cycles -= 12;
 40.2510 +                        break;
 40.2511 +                        case 0xC9: /*LEAVE*/
 40.2512 +                        templ=SP;
 40.2513 +                        SP=BP;
 40.2514 +                        tempw=readmemw(ss,SP);   SP+=2;
 40.2515 +                        if (abrt) { SP=templ; break; }
 40.2516 +                        BP=tempw;
 40.2517 +                        cycles -= 5;
 40.2518 +                        break;
 40.2519 +                        case 0xCA: /*RETF*/
 40.2520 +                        tempw=getword();
 40.2521 +                        if (msw&1)
 40.2522 +                        {
 40.2523 +                                pmoderetf(0,tempw);
 40.2524 +                                break;
 40.2525 +                        }
 40.2526 +                        tempw2=CPL;
 40.2527 +                        if (ssegs) ss=oldss;
 40.2528 +                        oxpc=pc;
 40.2529 +                        pc=readmemw(ss,SP);
 40.2530 +                        loadcs(readmemw(ss,SP+2));
 40.2531 +                        if (abrt) break;
 40.2532 +                        SP+=4+tempw;
 40.2533 +                        cycles -= 15;
 40.2534 +                        break;
 40.2535 +                        case 0xCB: /*RETF*/
 40.2536 +                        if (msw&1)
 40.2537 +                        {
 40.2538 +                                pmoderetf(0,0);
 40.2539 +                                break;
 40.2540 +                        }
 40.2541 +                        tempw2=CPL;
 40.2542 +                        if (ssegs) ss=oldss;
 40.2543 +                        oxpc=pc;
 40.2544 +                        pc=readmemw(ss,SP);
 40.2545 +                        loadcs(readmemw(ss,SP+2));
 40.2546 +                        if (abrt) break;
 40.2547 +                        SP+=4;
 40.2548 +                        cycles -= 15;
 40.2549 +                        break;
 40.2550 +                        case 0xCC: /*INT 3*/
 40.2551 +                        if (msw&1)
 40.2552 +                        {
 40.2553 +                                pmodeint(3,1);
 40.2554 +                                cycles -= 40;
 40.2555 +                        }
 40.2556 +                        else
 40.2557 +                        {
 40.2558 +                                if (ssegs) ss=oldss;
 40.2559 +                                writememw(ss,((SP-2)&0xFFFF),flags);
 40.2560 +                                writememw(ss,((SP-4)&0xFFFF),CS);
 40.2561 +                                writememw(ss,((SP-6)&0xFFFF),pc);
 40.2562 +                                SP-=6;
 40.2563 +                                addr=3<<2;
 40.2564 +//                                flags&=~I_FLAG;
 40.2565 +                                flags&=~T_FLAG;
 40.2566 +                                oxpc=pc;
 40.2567 +                                pc=readmemw(0,addr);
 40.2568 +                                loadcs(readmemw(0,addr+2));
 40.2569 +                                cycles -= 23;
 40.2570 +                        }
 40.2571 +                        break;
 40.2572 +                        case 0xCD: /*INT*/
 40.2573 +                        lastpc=pc;
 40.2574 +                        lastcs=CS;
 40.2575 +                        temp=readmemb(cs,pc); pc++;
 40.2576 +                        intrt:
 40.2577 +                                pclog("INT %02X  %04X %04X %04X %04X  %04X:%04X\n", temp, AX, BX, CX, DX, CS, pc);
 40.2578 +                        if (1)
 40.2579 +                        {
 40.2580 +                                if (msw&1)
 40.2581 +                                {
 40.2582 +//                                        pclog("PMODE int %02X %04X at %04X:%04X  ",temp,AX,CS,pc);
 40.2583 +                                        pmodeint(temp,1);
 40.2584 +                                        cycles -= 40;
 40.2585 +//                                        pclog("to %04X:%04X\n",CS,pc);
 40.2586 +                                }
 40.2587 +                                else
 40.2588 +                                {
 40.2589 +                                        if (ssegs) ss=oldss;
 40.2590 +                                        writememw(ss,((SP-2)&0xFFFF),flags);
 40.2591 +                                        writememw(ss,((SP-4)&0xFFFF),CS);
 40.2592 +                                        writememw(ss,((SP-6)&0xFFFF),pc);
 40.2593 +                                        SP-=6;
 40.2594 +                                        addr=temp<<2;
 40.2595 +//                                        flags&=~I_FLAG;
 40.2596 +                                        flags&=~T_FLAG;
 40.2597 +                                        oxpc=pc;
 40.2598 +//                                        pclog("%04X:%04X : ",CS,pc);
 40.2599 +                                        pc=readmemw(0,addr);
 40.2600 +                                        loadcs(readmemw(0,addr+2));
 40.2601 +                                        cycles -= 23;
 40.2602 +//                                        pclog("INT %02X - %04X %04X:%04X\n",temp,addr,CS,pc);
 40.2603 +                                }
 40.2604 +                        }
 40.2605 +                        break;
 40.2606 +                        case 0xCE: /*INTO*/
 40.2607 +                        if (flags&V_FLAG)
 40.2608 +                        {
 40.2609 +                                temp=4;
 40.2610 +                                goto intrt;
 40.2611 +/*                                pclog("INTO interrupt!\n");
 40.2612 +                                dumpregs();
 40.2613 +                                exit(-1);*/
 40.2614 +                        }
 40.2615 +                        cycles-=3;
 40.2616 +                        break;
 40.2617 +                        case 0xCF: /*IRET*/
 40.2618 +                        if (ssegs) ss=oldss;
 40.2619 +                        if (msw&1)
 40.2620 +                        {
 40.2621 +                                optype=IRET;
 40.2622 +                                pmodeiret(0);
 40.2623 +                                optype=0;
 40.2624 +                        }
 40.2625 +                        else
 40.2626 +                        {
 40.2627 +                                tempw=CS;
 40.2628 +                                tempw2=pc;
 40.2629 +                                inint=0;
 40.2630 +                                oxpc=pc;
 40.2631 +                                pc=readmemw(ss,SP);
 40.2632 +                                loadcs(readmemw(ss,((SP+2)&0xFFFF)));
 40.2633 +                                flags=(readmemw(ss,((SP+4)&0xFFFF))&0x0FD5)|2;
 40.2634 +                                SP+=6;
 40.2635 +                        }
 40.2636 +                        cycles -= 17;
 40.2637 +                        break;
 40.2638 +                        
 40.2639 +                        case 0xD0:
 40.2640 +                        fetchea();
 40.2641 +                        temp=geteab(); if (abrt) break;
 40.2642 +                        switch (rmdat&0x38)
 40.2643 +                        {
 40.2644 +                                case 0x00: /*ROL b,1*/
 40.2645 +                                seteab((temp<<1)|((temp&0x80)?1:0)); if (abrt) break;
 40.2646 +                                if (temp&0x80) flags|=C_FLAG;
 40.2647 +                                else           flags&=~C_FLAG;
 40.2648 +                                temp<<=1;
 40.2649 +                                if (flags&C_FLAG) temp|=1;
 40.2650 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2651 +                                else                          flags&=~V_FLAG;
 40.2652 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2653 +                                break;
 40.2654 +                                case 0x08: /*ROR b,1*/
 40.2655 +                                seteab((temp>>1)|((temp&1)?0x80:0)); if (abrt) break;
 40.2656 +                                if (temp&1) flags|=C_FLAG;
 40.2657 +                                else        flags&=~C_FLAG;
 40.2658 +                                temp>>=1;
 40.2659 +                                if (flags&C_FLAG) temp|=0x80;
 40.2660 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2661 +                                else                       flags&=~V_FLAG;
 40.2662 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2663 +                                break;
 40.2664 +                                case 0x10: /*RCL b,1*/
 40.2665 +                                temp2=flags&C_FLAG;
 40.2666 +                                seteab((temp<<1)|temp2); if (abrt) break;
 40.2667 +                                if (temp&0x80) flags|=C_FLAG;
 40.2668 +                                else           flags&=~C_FLAG;
 40.2669 +                                temp<<=1;
 40.2670 +                                if (temp2) temp|=1;
 40.2671 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2672 +                                else                          flags&=~V_FLAG;
 40.2673 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2674 +                                break;
 40.2675 +                                case 0x18: /*RCR b,1*/
 40.2676 +                                temp2=flags&C_FLAG;
 40.2677 +                                seteab((temp>>1)|(temp2?0x80:0)); if (abrt) break;
 40.2678 +                                if (temp&1) flags|=C_FLAG;
 40.2679 +                                else        flags&=~C_FLAG;
 40.2680 +                                temp>>=1;
 40.2681 +                                if (temp2) temp|=0x80;
 40.2682 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2683 +                                else                       flags&=~V_FLAG;
 40.2684 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2685 +                                break;
 40.2686 +                                case 0x20: case 0x30: /*SHL b,1*/
 40.2687 +                                seteab(temp<<1); if (abrt) break;
 40.2688 +                                setznp8(temp<<1);
 40.2689 +                                if (temp&0x80) flags|=C_FLAG;
 40.2690 +                                if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
 40.2691 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2692 +                                break;
 40.2693 +                                case 0x28: /*SHR b,1*/
 40.2694 +                                seteab(temp>>1); if (abrt) break;
 40.2695 +                                setznp8(temp>>1);
 40.2696 +                                if (temp&1) flags|=C_FLAG;
 40.2697 +                                if (temp&0x80) flags|=V_FLAG;
 40.2698 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2699 +                                break;
 40.2700 +                                case 0x38: /*SAR b,1*/
 40.2701 +                                seteab((temp>>1)|(temp&0x80)); if (abrt) break;
 40.2702 +                                setznp8((temp>>1)|(temp&0x80));
 40.2703 +                                if (temp&1) flags|=C_FLAG;
 40.2704 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2705 +                                break;
 40.2706 +
 40.2707 +//                                default:
 40.2708 +//                                pclog("Bad D0 opcode %02X\n",rmdat&0x38);
 40.2709 +//                                dumpregs();
 40.2710 +//                                exit(-1);
 40.2711 +                        }
 40.2712 +                        break;
 40.2713 +                        case 0xD1:
 40.2714 +                        fetchea();
 40.2715 +                        tempw=geteaw(); if (abrt) break;
 40.2716 +                        switch (rmdat&0x38)
 40.2717 +                        {
 40.2718 +                                case 0x00: /*ROL w,1*/
 40.2719 +                                seteaw((tempw<<1)|(tempw>>15)); if (abrt) break;
 40.2720 +                                if (tempw&0x8000) flags|=C_FLAG;
 40.2721 +                                else              flags&=~C_FLAG;
 40.2722 +                                tempw<<=1;
 40.2723 +                                if (flags&C_FLAG) tempw|=1;
 40.2724 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2725 +                                else                            flags&=~V_FLAG;
 40.2726 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2727 +                                break;
 40.2728 +                                case 0x08: /*ROR w,1*/
 40.2729 +                                seteaw((tempw>>1)|(tempw<<15)); if (abrt) break;
 40.2730 +                                if (tempw&1) flags|=C_FLAG;
 40.2731 +                                else         flags&=~C_FLAG;
 40.2732 +                                tempw>>=1;
 40.2733 +                                if (flags&C_FLAG) tempw|=0x8000;
 40.2734 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2735 +                                else                           flags&=~V_FLAG;
 40.2736 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2737 +                                break;
 40.2738 +                                case 0x10: /*RCL w,1*/
 40.2739 +                                temp2=flags&C_FLAG;
 40.2740 +                                seteaw((tempw<<1)|temp2);       if (abrt) break;
 40.2741 +                                if (tempw&0x8000) flags|=C_FLAG;
 40.2742 +                                else              flags&=~C_FLAG;
 40.2743 +                                tempw<<=1;
 40.2744 +                                if (temp2) tempw|=1;
 40.2745 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2746 +                                else                            flags&=~V_FLAG;
 40.2747 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2748 +                                break;
 40.2749 +                                case 0x18: /*RCR w,1*/
 40.2750 +                                temp2=flags&C_FLAG;
 40.2751 +                                seteaw((tempw>>1)|(temp2?0x8000:0));      if (abrt) break;
 40.2752 +                                if (tempw&1) flags|=C_FLAG;
 40.2753 +                                else         flags&=~C_FLAG;
 40.2754 +                                tempw>>=1;
 40.2755 +                                if (temp2) tempw|=0x8000;
 40.2756 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2757 +                                else                           flags&=~V_FLAG;
 40.2758 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2759 +                                break;
 40.2760 +                                case 0x20: case 0x30: /*SHL w,1*/
 40.2761 +                                seteaw(tempw<<1);       if (abrt) break;
 40.2762 +                                setznp16(tempw<<1);
 40.2763 +                                if (tempw&0x8000) flags|=C_FLAG;
 40.2764 +                                if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
 40.2765 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2766 +                                break;
 40.2767 +                                case 0x28: /*SHR w,1*/
 40.2768 +                                seteaw(tempw>>1);       if (abrt) break;
 40.2769 +                                setznp16(tempw>>1);
 40.2770 +                                if (tempw&1) flags|=C_FLAG;
 40.2771 +                                if (tempw&0x8000) flags|=V_FLAG;
 40.2772 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2773 +                                break;
 40.2774 +                                case 0x38: /*SAR w,1*/
 40.2775 +                                seteaw((tempw>>1)|(tempw&0x8000)); if (abrt) break;
 40.2776 +                                setznp16((tempw>>1)|(tempw&0x8000));
 40.2777 +                                if (tempw&1) flags|=C_FLAG;
 40.2778 +                                cycles -= (mod == 3) ? 2 : 7;
 40.2779 +                                break;
 40.2780 +
 40.2781 +                                default:
 40.2782 +                                pclog("Bad D1 opcode %02X\n",rmdat&0x38);
 40.2783 +                        }
 40.2784 +                        break;
 40.2785 +
 40.2786 +                        case 0xD2:
 40.2787 +                        fetchea();
 40.2788 +                        temp=geteab();  if (abrt) break;
 40.2789 +                        c=CL&31;
 40.2790 +//                        cycles-=c;
 40.2791 +                        if (!c) break;
 40.2792 +//                        if (c>7) pclog("Shiftb %i %02X\n",rmdat&0x38,c);
 40.2793 +                        cycles -= c;
 40.2794 +                        switch (rmdat&0x38)
 40.2795 +                        {
 40.2796 +                                case 0x00: /*ROL b,CL*/
 40.2797 +                                while (c>0)
 40.2798 +                                {
 40.2799 +                                        temp2=(temp&0x80)?1:0;
 40.2800 +                                        temp=(temp<<1)|temp2;
 40.2801 +                                        c--;
 40.2802 +                                }
 40.2803 +                                seteab(temp); if (abrt) break;
 40.2804 +                                flags&=~(C_FLAG|V_FLAG);
 40.2805 +                                if (temp2) flags|=C_FLAG;
 40.2806 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2807 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2808 +                                break;
 40.2809 +                                case 0x08: /*ROR b,CL*/
 40.2810 +                                while (c>0)
 40.2811 +                                {
 40.2812 +                                        temp2=temp&1;
 40.2813 +                                        temp>>=1;
 40.2814 +                                        if (temp2) temp|=0x80;
 40.2815 +                                        c--;
 40.2816 +                                }
 40.2817 +                                seteab(temp); if (abrt) break;
 40.2818 +                                flags&=~(C_FLAG|V_FLAG);
 40.2819 +                                if (temp2) flags|=C_FLAG;
 40.2820 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2821 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2822 +                                break;
 40.2823 +                                case 0x10: /*RCL b,CL*/
 40.2824 +                                tempc=flags&C_FLAG;
 40.2825 +                                while (c>0)
 40.2826 +                                {
 40.2827 +                                        templ=tempc;
 40.2828 +                                        tempc=temp&0x80;
 40.2829 +                                        temp<<=1;
 40.2830 +                                        if (templ) temp|=1;
 40.2831 +                                        c--;
 40.2832 +                                }
 40.2833 +                                seteab(temp); if (abrt) break;
 40.2834 +                                flags&=~(C_FLAG|V_FLAG);
 40.2835 +                                if (tempc) flags|=C_FLAG;
 40.2836 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 40.2837 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2838 +                                break;
 40.2839 +                                case 0x18: /*RCR b,CL*/
 40.2840 +                                tempc=flags&C_FLAG;
 40.2841 +                                while (c>0)
 40.2842 +                                {
 40.2843 +                                        templ=tempc;
 40.2844 +                                        tempc=temp&1;
 40.2845 +                                        temp>>=1;
 40.2846 +                                        if (templ) temp|=0x80;
 40.2847 +                                        c--;
 40.2848 +                                }
 40.2849 +                                seteab(temp); if (abrt) break;
 40.2850 +                                flags&=~(C_FLAG|V_FLAG);
 40.2851 +                                if (tempc) flags|=C_FLAG;
 40.2852 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 40.2853 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2854 +                                break;
 40.2855 +                                case 0x20: case 0x30: /*SHL b,CL*/
 40.2856 +                                seteab(temp<<c); if (abrt) break;
 40.2857 +                                setznp8(temp<<c);
 40.2858 +                                if ((temp<<(c-1))&0x80) flags|=C_FLAG;
 40.2859 +                                if (((temp<<c)^(temp<<(c-1)))&0x80) flags|=V_FLAG;
 40.2860 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2861 +                                break;
 40.2862 +                                case 0x28: /*SHR b,CL*/
 40.2863 +                                seteab(temp>>c); if (abrt) break;
 40.2864 +                                setznp8(temp>>c);
 40.2865 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
 40.2866 +                                if (c==1 && temp&0x80) flags|=V_FLAG;
 40.2867 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2868 +                                break;
 40.2869 +                                case 0x38: /*SAR b,CL*/
 40.2870 +                                tempc=(temp>>(c-1))&1;
 40.2871 +                                while (c>0)
 40.2872 +                                {
 40.2873 +                                        temp>>=1;
 40.2874 +                                        if (temp&0x40) temp|=0x80;
 40.2875 +                                        c--;
 40.2876 +                                }
 40.2877 +                                seteab(temp); if (abrt) break;
 40.2878 +                                setznp8(temp);
 40.2879 +                                if (tempc) flags|=C_FLAG;
 40.2880 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2881 +                                break;
 40.2882 +
 40.2883 +//                                default:
 40.2884 +//                                pclog("Bad D2 opcode %02X\n",rmdat&0x38);
 40.2885 +//                                dumpregs();
 40.2886 +//                                exit(-1);
 40.2887 +                        }
 40.2888 +                        break;
 40.2889 +
 40.2890 +                        case 0xD3:
 40.2891 +                        fetchea();
 40.2892 +                        tempw=geteaw(); if (abrt) break;
 40.2893 +                        c=CL&31;
 40.2894 +                        if (!c) break;
 40.2895 +                        cycles -= c;
 40.2896 +                        switch (rmdat&0x38)
 40.2897 +                        {
 40.2898 +                                case 0x00: /*ROL w,CL*/
 40.2899 +                                while (c>0)
 40.2900 +                                {
 40.2901 +                                        temp=(tempw&0x8000)?1:0;
 40.2902 +                                        tempw=(tempw<<1)|temp;
 40.2903 +                                        c--;
 40.2904 +                                }
 40.2905 +                                seteaw(tempw); if (abrt) break;
 40.2906 +                                flags&=~(C_FLAG|V_FLAG);
 40.2907 +                                if (temp) flags|=C_FLAG;
 40.2908 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2909 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2910 +                                break;
 40.2911 +                                case 0x08: /*ROR w,CL*/
 40.2912 +                                while (c>0)
 40.2913 +                                {
 40.2914 +                                        tempw2=(tempw&1)?0x8000:0;
 40.2915 +                                        tempw=(tempw>>1)|tempw2;
 40.2916 +                                        c--;
 40.2917 +                                }
 40.2918 +                                seteaw(tempw); if (abrt) break;
 40.2919 +                                flags&=~(C_FLAG|V_FLAG);
 40.2920 +                                if (tempw2) flags|=C_FLAG;
 40.2921 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2922 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2923 +                                break;
 40.2924 +                                case 0x10: /*RCL w,CL*/
 40.2925 +                                tempc=flags&C_FLAG;
 40.2926 +                                while (c>0)
 40.2927 +                                {
 40.2928 +                                        templ=tempc;
 40.2929 +                                        tempc=tempw&0x8000;
 40.2930 +                                        tempw=(tempw<<1)|templ;
 40.2931 +                                        c--;
 40.2932 +                                }
 40.2933 +                                seteaw(tempw); if (abrt) break;
 40.2934 +                                flags&=~(C_FLAG|V_FLAG);
 40.2935 +                                if (tempc) flags|=C_FLAG;
 40.2936 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 40.2937 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2938 +                                break;
 40.2939 +                                case 0x18: /*RCR w,CL*/
 40.2940 +                                tempc=flags&C_FLAG;
 40.2941 +                                while (c>0)
 40.2942 +                                {
 40.2943 +                                        templ=tempc;
 40.2944 +                                        tempw2=(templ&1)?0x8000:0;
 40.2945 +                                        tempc=tempw&1;
 40.2946 +                                        tempw=(tempw>>1)|tempw2;
 40.2947 +                                        c--;
 40.2948 +                                }
 40.2949 +                                seteaw(tempw); if (abrt) break;
 40.2950 +                                flags&=~(C_FLAG|V_FLAG);
 40.2951 +                                if (tempc) flags|=C_FLAG;
 40.2952 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 40.2953 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2954 +                                break;
 40.2955 +
 40.2956 +                                case 0x20: case 0x30: /*SHL w,CL*/
 40.2957 +                                seteaw(tempw<<c); if (abrt) break;
 40.2958 +                                setznp16(tempw<<c);
 40.2959 +                                if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
 40.2960 +                                if (((tempw<<c)^(tempw<<(c-1)))&0x8000) flags|=V_FLAG;
 40.2961 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2962 +                                break;
 40.2963 +
 40.2964 +                                case 0x28:            /*SHR w,CL*/
 40.2965 +                                seteaw(tempw>>c); if (abrt) break;
 40.2966 +                                setznp16(tempw>>c);
 40.2967 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
 40.2968 +                                if (c==1 && tempw&0x8000) flags|=V_FLAG;
 40.2969 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2970 +                                break;
 40.2971 +
 40.2972 +                                case 0x38:            /*SAR w,CL*/
 40.2973 +                                tempw2=tempw&0x8000;
 40.2974 +                                tempc=((int16_t)tempw>>(c-1))&1;
 40.2975 +                                while (c>0)
 40.2976 +                                {
 40.2977 +                                        tempw=(tempw>>1)|tempw2;
 40.2978 +                                        c--;
 40.2979 +                                }
 40.2980 +                                seteaw(tempw); if (abrt) break;
 40.2981 +                                setznp16(tempw);
 40.2982 +                                if (tempc) flags|=C_FLAG;
 40.2983 +                                cycles -= (mod == 3) ? 5 : 8;
 40.2984 +                                break;
 40.2985 +
 40.2986 +//                                default:
 40.2987 +//                                pclog("Bad D3 opcode %02X\n",rmdat&0x38);
 40.2988 +//                                dumpregs();
 40.2989 +//                                exit(-1);
 40.2990 +                        }
 40.2991 +                        break;
 40.2992 +
 40.2993 +                        case 0xD4: /*AAM*/
 40.2994 +                        tempws=readmemb(cs,pc); pc++;
 40.2995 +                        AH=AL/tempws;
 40.2996 +                        AL%=tempws;
 40.2997 +                        setznp16(AX);
 40.2998 +                        cycles -= 16;
 40.2999 +                        break;
 40.3000 +                        case 0xD5: /*AAD*/
 40.3001 +                        tempws=readmemb(cs,pc); pc++;
 40.3002 +                        AL=(AH*tempws)+AL;
 40.3003 +                        AH=0;
 40.3004 +                        setznp16(AX);
 40.3005 +                        cycles -= 14;
 40.3006 +                        break;
 40.3007 +                        case 0xD6: /*SETALC*/
 40.3008 +                        AL=(flags&C_FLAG)?0xFF:0;
 40.3009 +                        cycles -= 3;
 40.3010 +                        break;
 40.3011 +                        case 0xD7: /*XLAT*/
 40.3012 +                        addr=(BX+AL)&0xFFFF;
 40.3013 +                        temp=readmemb(ds,addr); if (abrt) break;
 40.3014 +                        AL=temp;
 40.3015 +                        cycles -= 5;
 40.3016 +                        break;
 40.3017 +                        case 0xD9: case 0xDA: case 0xDB: case 0xDD:     /*ESCAPE*/
 40.3018 +                        case 0xD8:
 40.3019 +                        case 0xDC:
 40.3020 +                        case 0xDE:
 40.3021 +                        case 0xDF:
 40.3022 +                        if ((msw & 6) == 4)
 40.3023 +                        {
 40.3024 +                                pc=oldpc;
 40.3025 +                                pmodeint(7,0);
 40.3026 +                                cycles -= 40;
 40.3027 +                        }
 40.3028 +                        else
 40.3029 +                        {
 40.3030 +                                fetchea();
 40.3031 +                        }
 40.3032 +                        break;
 40.3033 +
 40.3034 +                        case 0xE0: /*LOOPNE*/
 40.3035 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 40.3036 +                        CX--;
 40.3037 +                        if (CX && !(flags&Z_FLAG)) { pc+=offset; cycles -= 4; cycles -= 2; }
 40.3038 +                        cycles -= 4;
 40.3039 +                        break;
 40.3040 +                        case 0xE1: /*LOOPE*/
 40.3041 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 40.3042 +                        CX--;
 40.3043 +                        if (CX && (flags&Z_FLAG)) { pc+=offset; cycles -= 4; cycles -= 2; }
 40.3044 +                        cycles -= 4;
 40.3045 +                        break;
 40.3046 +                        case 0xE2: /*LOOP*/
 40.3047 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 40.3048 +                        CX--;
 40.3049 +                        if (CX) { pc+=offset; cycles -= 4; cycles -= 2; }
 40.3050 +                        cycles -= 4;
 40.3051 +                        break;
 40.3052 +                        case 0xE3: /*JCXZ*/
 40.3053 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 40.3054 +                        if (!CX) { pc+=offset; cycles -= 4; cycles -= 2; }
 40.3055 +                        cycles-=4;
 40.3056 +                        break;
 40.3057 +
 40.3058 +                        case 0xE4: /*IN AL*/
 40.3059 +                        temp=readmemb(cs,pc);
 40.3060 +                        checkio_perm(temp);
 40.3061 +                        pc++;
 40.3062 +                        AL=inb(temp);
 40.3063 +                        cycles -= 5;
 40.3064 +                        break;
 40.3065 +                        case 0xE5: /*IN AX*/
 40.3066 +                        temp=readmemb(cs,pc);
 40.3067 +                        checkio_perm(temp);
 40.3068 +                        checkio_perm(temp+1);
 40.3069 +                        pc++;
 40.3070 +                        AX=inw(temp);
 40.3071 +                        cycles -= 5;
 40.3072 +                        break;
 40.3073 +                        case 0xE6: /*OUT AL*/
 40.3074 +                        temp=readmemb(cs,pc);
 40.3075 +                        checkio_perm(temp);
 40.3076 +                        pc++;
 40.3077 +                        outb(temp,AL);
 40.3078 +                        cycles -= 3;
 40.3079 +                        break;
 40.3080 +                        case 0xE7: /*OUT AX*/
 40.3081 +                        temp=readmemb(cs,pc);
 40.3082 +                        checkio_perm(temp);
 40.3083 +                        checkio_perm(temp+1);
 40.3084 +                        pc++;
 40.3085 +                        outw(temp,AX);
 40.3086 +                        cycles -= 3;
 40.3087 +                        break;
 40.3088 +
 40.3089 +                        case 0xE8: /*CALL rel 16*/
 40.3090 +                        tempw=getword(); if (abrt) break;
 40.3091 +                        if (ssegs) ss=oldss;
 40.3092 +                        writememw(ss,((SP-2)&0xFFFF),pc); if (abrt) break;
 40.3093 +                        SP-=2;
 40.3094 +                        pc+=(int16_t)tempw;
 40.3095 +                        cycles -= 7;
 40.3096 +                        break;
 40.3097 +                        case 0xE9: /*JMP rel 16*/
 40.3098 +                        tempw=getword(); if (abrt) break;
 40.3099 +                        pc+=(int16_t)tempw;
 40.3100 +                        cycles -= 7;
 40.3101 +                        break;
 40.3102 +                        case 0xEA: /*JMP far*/
 40.3103 +                        addr=getword();
 40.3104 +                        tempw=getword(); if (abrt) { if (output==3) pclog("JMP ABRT\n"); break; }
 40.3105 +                        oxpc=pc;
 40.3106 +                        pc=addr;
 40.3107 +                        loadcsjmp(tempw,oxpc);
 40.3108 +                        cycles -= 11;
 40.3109 +                        break;
 40.3110 +                        case 0xEB: /*JMP rel*/
 40.3111 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 40.3112 +                        pc+=offset;
 40.3113 +                        cycles -= 7;
 40.3114 +                        break;
 40.3115 +                        case 0xEC: /*IN AL,DX*/
 40.3116 +                        checkio_perm(DX);
 40.3117 +                        AL=inb(DX);
 40.3118 +                        cycles -= 5;
 40.3119 +                        break;
 40.3120 +                        case 0xED: /*IN AX,DX*/
 40.3121 +                        checkio_perm(DX);
 40.3122 +                        checkio_perm(DX+1);
 40.3123 +                        AX=inw(DX);
 40.3124 +                        cycles -= 5;
 40.3125 +                        break;
 40.3126 +                        case 0xEE: /*OUT DX,AL*/
 40.3127 +                        checkio_perm(DX);
 40.3128 +                        outb(DX,AL);
 40.3129 +                        cycles -= 4;
 40.3130 +                        break;
 40.3131 +                        case 0xEF: /*OUT DX,AX*/
 40.3132 +                        checkio_perm(DX);
 40.3133 +                        checkio_perm(DX+1);
 40.3134 +                        outw(DX,AX);
 40.3135 +                        cycles -= 4;
 40.3136 +                        break;
 40.3137 +
 40.3138 +                        case 0xF0: /*LOCK*/
 40.3139 +                        break;
 40.3140 +
 40.3141 +                        case 0xF2: /*REPNE*/
 40.3142 +                        rep386(0);
 40.3143 +                        break;
 40.3144 +                        case 0xF3: /*REPE*/
 40.3145 +                        rep386(1);
 40.3146 +                        break;
 40.3147 +
 40.3148 +                        case 0xF4: /*HLT*/
 40.3149 +                        inhlt=1;
 40.3150 +                        pc--;
 40.3151 +                        cycles -= 2;
 40.3152 +/*                        if (!(flags & I_FLAG))
 40.3153 +                        {
 40.3154 +                                pclog("Complete HLT\n");
 40.3155 +                                dumpregs();
 40.3156 +                                exit(-1);
 40.3157 +                        }*/
 40.3158 +                        break;
 40.3159 +                        case 0xF5: /*CMC*/
 40.3160 +                        flags^=C_FLAG;
 40.3161 +                        cycles -= 2;
 40.3162 +                        break;
 40.3163 +
 40.3164 +                        case 0xF6:
 40.3165 +                        fetchea();
 40.3166 +                        temp=geteab(); if (abrt) break;
 40.3167 +                        switch (rmdat&0x38)
 40.3168 +                        {
 40.3169 +                                case 0x00: /*TEST b,#8*/
 40.3170 +                                temp2=readmemb(cs,pc); pc++; if (abrt) break;
 40.3171 +//                                pclog("TEST %02X,%02X\n",temp,temp2);
 40.3172 +/*                        if (cs==0x700 && !temp && temp2==0x10)
 40.3173 +                        {
 40.3174 +                                dumpregs();
 40.3175 +                                exit(-1);
 40.3176 +                        }*/
 40.3177 +                                temp&=temp2;
 40.3178 +                                setznp8(temp);
 40.3179 +                                cycles -= (mod == 3) ? 3 : 6;
 40.3180 +                                break;
 40.3181 +                                case 0x10: /*NOT b*/
 40.3182 +                                temp=~temp;
 40.3183 +                                seteab(temp);
 40.3184 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3185 +                                break;
 40.3186 +                                case 0x18: /*NEG b*/
 40.3187 +                                setsub8(0,temp);
 40.3188 +                                temp=0-temp;
 40.3189 +                                seteab(temp);
 40.3190 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3191 +                                break;
 40.3192 +                                case 0x20: /*MUL AL,b*/
 40.3193 +//                                setznp8(AL);
 40.3194 +                                AX=AL*temp;
 40.3195 +//                                if (AX) flags&=~Z_FLAG;
 40.3196 +//                                else    flags|=Z_FLAG;
 40.3197 +                                if (AH) flags|=(C_FLAG|V_FLAG);
 40.3198 +                                else    flags&=~(C_FLAG|V_FLAG);
 40.3199 +                                cycles -= (mod == 3) ? 13 : 16;
 40.3200 +                                break;
 40.3201 +                                case 0x28: /*IMUL AL,b*/
 40.3202 +//                                setznp8(AL);
 40.3203 +                                tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
 40.3204 +                                AX=tempws&0xFFFF;
 40.3205 +//                                if (AX) flags&=~Z_FLAG;
 40.3206 +//                                else    flags|=Z_FLAG;
 40.3207 +                                if (AH && AH!=0xFF) flags|=(C_FLAG|V_FLAG);
 40.3208 +                                else                flags&=~(C_FLAG|V_FLAG);
 40.3209 +                                cycles -= (mod == 3) ? 13 : 16;
 40.3210 +                                break;
 40.3211 +                                case 0x30: /*DIV AL,b*/
 40.3212 +                                tempw=AX;
 40.3213 +                                if (temp) tempw2=tempw/temp;
 40.3214 +//                                pclog("DIV %04X/%02X %04X:%04X\n",tempw,temp,CS,pc);
 40.3215 +                                if (temp && !(tempw2&0xFF00))
 40.3216 +                                {
 40.3217 +                                        tempw2=tempw%temp;
 40.3218 +                                        AH=tempw2;
 40.3219 +                                        tempw/=temp;
 40.3220 +                                        AL=tempw&0xFF;
 40.3221 +                                        flags|=0x8D5; /*Not a Cyrix*/
 40.3222 +                                }
 40.3223 +                                else
 40.3224 +                                {
 40.3225 +                                        pclog("DIVb BY 0 %04X:%04X\n",cs>>4,pc);
 40.3226 +                                        pc=oldpc;
 40.3227 +                                        if (msw&1) pmodeint(0,0);
 40.3228 +                                        else
 40.3229 +                                        {
 40.3230 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 40.3231 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 40.3232 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 40.3233 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 40.3234 +                                                SP-=6;
 40.3235 +                                                flags&=~I_FLAG;
 40.3236 +                                                oxpc=pc;
 40.3237 +                                                pc=readmemw(0,0);
 40.3238 +                                                loadcs(readmemw(0,2));
 40.3239 +                                        }
 40.3240 +//                                                cs=loadcs(CS);
 40.3241 +//                                                cs=CS<<4;
 40.3242 +//                                        pclog("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30);
 40.3243 +//                                        dumpregs();
 40.3244 +//                                        exit(-1);
 40.3245 +                                }
 40.3246 +                                cycles -= (mod == 3) ? 14 : 17;
 40.3247 +                                break;
 40.3248 +                                case 0x38: /*IDIV AL,b*/
 40.3249 +//                                pclog("IDIV %04X/%02X\n",tempw,temp);
 40.3250 +                                tempws=(int)(int16_t)AX;
 40.3251 +                                if (temp!=0) tempws2=tempws/(int)((int8_t)temp);
 40.3252 +                                temps=tempws2&0xFF;
 40.3253 +                                if ((temp!=0) && ((int)temps==tempws2))
 40.3254 +                                {
 40.3255 +                                        tempw2=tempws%(int)((int8_t)temp);
 40.3256 +                                        AH=tempw2&0xFF;
 40.3257 +                                        AL=tempws2&0xFF;
 40.3258 +                                        if (!cpu_iscyrix) flags|=0x8D5; /*Not a Cyrix*/
 40.3259 +                                }
 40.3260 +                                else
 40.3261 +                                {
 40.3262 +                                        pclog("IDIVb exception - %X / %08X = %X\n",tempws,temp,tempws2);
 40.3263 +//                                        pclog("IDIVb BY 0 %04X:%04X\n",cs>>4,pc);
 40.3264 +                                        pc=oldpc;
 40.3265 +                                        if (msw&1) pmodeint(0,0);
 40.3266 +                                        else
 40.3267 +                                        {
 40.3268 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 40.3269 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 40.3270 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 40.3271 +                                                SP-=6;
 40.3272 +                                                flags&=~I_FLAG;
 40.3273 +                                                oxpc=pc;
 40.3274 +                                                pc=readmemw(0,0);
 40.3275 +                                                loadcs(readmemw(0,2));
 40.3276 +                                        }
 40.3277 +//                                                cs=loadcs(CS);
 40.3278 +//                                                cs=CS<<4;
 40.3279 +//                                        pclog("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
 40.3280 +                                }
 40.3281 +                                cycles -= (mod == 3) ? 17 : 20;
 40.3282 +                                break;
 40.3283 +
 40.3284 +                                default:
 40.3285 +                                pclog("Bad F6 opcode %02X\n",rmdat&0x38);
 40.3286 +                                x86illegal();
 40.3287 +//                                dumpregs();
 40.3288 +//                                exit(-1);
 40.3289 +                        }
 40.3290 +                        break;
 40.3291 +
 40.3292 +                        case 0xF7:
 40.3293 +                        fetchea();
 40.3294 +                        tempw=geteaw(); if (abrt) break;
 40.3295 +                        switch (rmdat&0x38)
 40.3296 +                        {
 40.3297 +                                case 0x00: /*TEST w*/
 40.3298 +                                tempw2=getword(); if (abrt) break;
 40.3299 +//                                if (output==3) pclog("TEST %04X %04X\n",tempw,tempw2);
 40.3300 +                                setznp16(tempw&tempw2);
 40.3301 +                                cycles -= (mod == 3) ? 3 : 6;
 40.3302 +                                break;
 40.3303 +                                case 0x10: /*NOT w*/
 40.3304 +                                seteaw(~tempw);
 40.3305 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3306 +                                break;
 40.3307 +                                case 0x18: /*NEG w*/
 40.3308 +                                setsub16(0,tempw);
 40.3309 +                                tempw=0-tempw;
 40.3310 +                                seteaw(tempw);
 40.3311 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3312 +                                break;
 40.3313 +                                case 0x20: /*MUL AX,w*/
 40.3314 +//                                setznp16(AX);
 40.3315 +                                templ=AX*tempw;
 40.3316 +                                AX=templ&0xFFFF;
 40.3317 +                                DX=templ>>16;
 40.3318 +//                                if (AX|DX) flags&=~Z_FLAG;
 40.3319 +//                                else       flags|=Z_FLAG;
 40.3320 +                                if (DX)    flags|=(C_FLAG|V_FLAG);
 40.3321 +                                else       flags&=~(C_FLAG|V_FLAG);
 40.3322 +                                cycles -= (mod == 3) ? 21 : 24;
 40.3323 +                                break;
 40.3324 +                                case 0x28: /*IMUL AX,w*/
 40.3325 +                                templ=(int)((int16_t)AX)*(int)((int16_t)tempw);
 40.3326 +                                AX=templ&0xFFFF;
 40.3327 +                                DX=templ>>16;
 40.3328 +                                if (DX && DX!=0xFFFF) flags|=(C_FLAG|V_FLAG);
 40.3329 +                                else                  flags&=~(C_FLAG|V_FLAG);
 40.3330 +                                cycles -= (mod == 3) ? 21 : 24;
 40.3331 +                                break;
 40.3332 +                                case 0x30: /*DIV AX,w*/
 40.3333 +                                templ=(DX<<16)|AX;
 40.3334 +                                if (tempw) templ2=templ/tempw;
 40.3335 +                                if (tempw && !(templ2&0xFFFF0000))
 40.3336 +                                {
 40.3337 +                                        tempw2=templ%tempw;
 40.3338 +                                        DX=tempw2;
 40.3339 +                                        templ/=tempw;
 40.3340 +                                        AX=templ&0xFFFF;
 40.3341 +                                        if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
 40.3342 +                                }
 40.3343 +                                else
 40.3344 +                                {
 40.3345 +//                                        AX=DX=0;
 40.3346 +//                                        break;
 40.3347 +                                        pclog("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins);
 40.3348 +//                                        dumpregs();
 40.3349 +//                                        exit(-1);
 40.3350 +                                        pc=oldpc;
 40.3351 +                                        if (msw&1) pmodeint(0,0);
 40.3352 +                                        else
 40.3353 +                                        {
 40.3354 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 40.3355 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 40.3356 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 40.3357 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 40.3358 +                                                SP-=6;
 40.3359 +                                                flags&=~I_FLAG;
 40.3360 +                                                oxpc=pc;
 40.3361 +                                                pc=readmemw(0,0);
 40.3362 +                                                loadcs(readmemw(0,2));
 40.3363 +                                        }
 40.3364 +//                                                cs=loadcs(CS);
 40.3365 +//                                                cs=CS<<4;
 40.3366 +//                                        pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x30);
 40.3367 +                                }
 40.3368 +                                cycles -= (mod == 3) ? 22 : 25;
 40.3369 +                                break;
 40.3370 +                                case 0x38: /*IDIV AX,w*/
 40.3371 +                                tempws=(int)((DX<<16)|AX);
 40.3372 +                                if (tempw!=0) tempws2=tempws/(int)((int16_t)tempw);
 40.3373 +                                temps16=tempws2&0xFFFF;
 40.3374 +//                                pclog("IDIV %i %i ",tempws,tempw);
 40.3375 +                                if ((tempw!=0) && ((int)temps16==tempws2))
 40.3376 +                                {
 40.3377 +                                        DX=tempws%(int)((int16_t)tempw);
 40.3378 +                                        AX=tempws2&0xFFFF;
 40.3379 +                                        if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
 40.3380 +                                }
 40.3381 +                                else
 40.3382 +                                {
 40.3383 +                                        pclog("IDIVw exception - %X / %08X = %X\n",tempws,tempw,tempws2);
 40.3384 +//                                        pclog("IDIVw BY 0 %04X:%04X\n",cs>>4,pc);
 40.3385 +//                                        DX=0;
 40.3386 +//                                        AX=0xFFFF;
 40.3387 +                                        pc=oldpc;
 40.3388 +                                        if (msw&1) pmodeint(0,0);
 40.3389 +                                        else
 40.3390 +                                        {
 40.3391 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 40.3392 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 40.3393 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 40.3394 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 40.3395 +                                                SP-=6;
 40.3396 +                                                flags&=~I_FLAG;
 40.3397 +                                                oxpc=pc;
 40.3398 +                                                pc=readmemw(0,0);
 40.3399 +                                                loadcs(readmemw(0,2));
 40.3400 +                                        }
 40.3401 +//                                                cs=loadcs(CS);
 40.3402 +//                                                cs=CS<<4;
 40.3403 +//                                        pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x38);
 40.3404 +                                }
 40.3405 +                                cycles -= (mod == 3) ? 25 : 28;
 40.3406 +                                break;
 40.3407 +
 40.3408 +                                default:
 40.3409 +                                pclog("Bad F7 opcode %02X\n",rmdat&0x38);
 40.3410 +                                x86illegal();
 40.3411 +//                                dumpregs();
 40.3412 +//                                exit(-1);
 40.3413 +                        }
 40.3414 +                        break;
 40.3415 +
 40.3416 +                        case 0xF8: /*CLC*/
 40.3417 +                        flags&=~C_FLAG;
 40.3418 +                        cycles -= 2;
 40.3419 +                        break;
 40.3420 +                        case 0xF9: /*STC*/
 40.3421 +//                        pclog("STC %04X\n",pc);
 40.3422 +                        flags|=C_FLAG;
 40.3423 +                        cycles -= 2;
 40.3424 +                        break;
 40.3425 +                        case 0xFA: /*CLI*/
 40.3426 +                        if (!IOPLp)
 40.3427 +                        {
 40.3428 +                                x86gpf(NULL,0);
 40.3429 +                        }
 40.3430 +                        else
 40.3431 +                           flags&=~I_FLAG;
 40.3432 +                        cycles -= 3;
 40.3433 +                        break;
 40.3434 +                        case 0xFB: /*STI*/
 40.3435 +                        if (!IOPLp)
 40.3436 +                        {
 40.3437 +                                x86gpf(NULL,0);
 40.3438 +                        }
 40.3439 +                        else
 40.3440 +                           flags|=I_FLAG;
 40.3441 +                        cycles -= 2;
 40.3442 +                        break;
 40.3443 +                        case 0xFC: /*CLD*/
 40.3444 +                        flags&=~D_FLAG;
 40.3445 +                        cycles -= 2;
 40.3446 +                        break;
 40.3447 +                        case 0xFD: /*STD*/
 40.3448 +                        flags|=D_FLAG;
 40.3449 +                        cycles -= 2;
 40.3450 +                        break;
 40.3451 +
 40.3452 +                        case 0xFE: /*INC/DEC b*/
 40.3453 +                        fetchea();
 40.3454 +                        temp=geteab(); if (abrt) break;
 40.3455 +                        if (rmdat&0x38)
 40.3456 +                        {
 40.3457 +                                seteab(temp-1); if (abrt) break;
 40.3458 +                                flags&=~V_FLAG;
 40.3459 +                                setsub8nc(temp,1);
 40.3460 +                                temp2=temp-1;
 40.3461 +                                if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
 40.3462 +                        }
 40.3463 +                        else
 40.3464 +                        {
 40.3465 +                                seteab(temp+1); if (abrt) break;
 40.3466 +                                flags&=~V_FLAG;
 40.3467 +                                setadd8nc(temp,1);
 40.3468 +                                temp2=temp+1;
 40.3469 +                                if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
 40.3470 +                        }
 40.3471 +                        cycles -= (mod == 3) ? 2 : 7;
 40.3472 +                        break;
 40.3473 +
 40.3474 +                        case 0xFF:
 40.3475 +                        fetchea();
 40.3476 +                        switch (rmdat&0x38)
 40.3477 +                        {
 40.3478 +                                case 0x00: /*INC w*/
 40.3479 +                                tempw=geteaw();  if (abrt) break;
 40.3480 +                                seteaw(tempw+1); if (abrt) break;
 40.3481 +                                setadd16nc(tempw,1);
 40.3482 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3483 +                                break;
 40.3484 +                                case 0x08: /*DEC w*/
 40.3485 +                                tempw=geteaw();  if (abrt) break;
 40.3486 +                                seteaw(tempw-1); if (abrt) break;
 40.3487 +                                setsub16nc(tempw,1);
 40.3488 +                                cycles -= (mod == 3) ? 2 : 7;
 40.3489 +                                break;
 40.3490 +                                case 0x10: /*CALL*/
 40.3491 +                                tempw=geteaw();
 40.3492 +                                if (abrt) break;
 40.3493 +                                if (ssegs) ss=oldss;
 40.3494 +                                writememw(ss,(SP-2)&0xFFFF,pc); if (abrt) break;
 40.3495 +                                SP-=2;
 40.3496 +                                pc=tempw;
 40.3497 +                                cycles -= (mod == 3) ? 7 : 11;
 40.3498 +                                break;
 40.3499 +                                case 0x18: /*CALL far*/
 40.3500 +                                tempw=readmemw(easeg,eaaddr);
 40.3501 +                                tempw2=readmemw(easeg,(eaaddr+2)); if (output==3) pclog("CALL FAR %04X:%04X\n",tempw,tempw2); if (abrt) break;
 40.3502 +                                tempw3=CS;
 40.3503 +                                templ2=pc;
 40.3504 +                                if (ssegs) ss=oldss;
 40.3505 +                                oxpc=pc;
 40.3506 +                                pc=tempw;
 40.3507 +                                optype=CALL;
 40.3508 +                                if (msw&1) loadcscall(tempw2);
 40.3509 +                                else       loadcs(tempw2);
 40.3510 +                                optype=0;
 40.3511 +                                if (abrt) break;
 40.3512 +                                oldss=ss;
 40.3513 +                                writememw(ss,(SP-2)&0xFFFF,tempw3);
 40.3514 +                                writememw(ss,((SP-4)&0xFFFF),templ2);
 40.3515 +                                SP-=4;
 40.3516 +                                cycles -= 16;
 40.3517 +                                break;
 40.3518 +                                case 0x20: /*JMP*/
 40.3519 +                                tempw=geteaw(); if (abrt) break;
 40.3520 +                                pc=tempw;
 40.3521 +                                cycles -= (mod == 3) ? 7 : 11;
 40.3522 +                                break;
 40.3523 +                                case 0x28: /*JMP far*/
 40.3524 +                                oxpc=pc;
 40.3525 +                                tempw=readmemw(easeg,eaaddr);
 40.3526 +                                tempw2=readmemw(easeg,eaaddr+2); if (abrt) break;
 40.3527 +                                pc=tempw;                                
 40.3528 +                                loadcsjmp(tempw2,oxpc); if (abrt) break;
 40.3529 +                                cycles -= 15;
 40.3530 +                                break;
 40.3531 +                                case 0x30: /*PUSH w*/
 40.3532 +                                tempw=geteaw(); if (abrt) break;
 40.3533 +                                if (ssegs) ss=oldss;
 40.3534 +                                writememw(ss,((SP-2)&0xFFFF),tempw); if (abrt) break;
 40.3535 +                                SP-=2;
 40.3536 +                                cycles -= (mod==3) ? 3 : 5;
 40.3537 +                                break;
 40.3538 +
 40.3539 +                                default:
 40.3540 +                                pclog("Bad FF opcode %02X\n",rmdat&0x38);
 40.3541 +                                x86illegal();
 40.3542 +                                //dumpregs();
 40.3543 +                                //exit(-1);
 40.3544 +                        }
 40.3545 +                        break;
 40.3546 +
 40.3547 +                        default:
 40.3548 +//                        pc--;
 40.3549 +//                        cycles-=8;
 40.3550 +//                        break;
 40.3551 +                        pclog("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
 40.3552 +                        x86illegal();
 40.3553 +//                        dumpregs();
 40.3554 +//                        exit(-1);
 40.3555 +                }
 40.3556 +                opcodeend:
 40.3557 +                pc&=0xFFFF;
 40.3558 +
 40.3559 +//                output = 3;
 40.3560 +/*                output = 3;
 40.3561 +                
 40.3562 +                if (pc == 0xcdd && CS == 0xf000)
 40.3563 +                {
 40.3564 +                        dumpregs();
 40.3565 +                        exit(-1);
 40.3566 +                }*/
 40.3567 +                //if (ins == 20768972) output = 3;
 40.3568 +                
 40.3569 +                if (ssegs)
 40.3570 +                {
 40.3571 +                        ds=oldds; _ds.limit=olddslimit; _ds.limitw=olddslimitw;
 40.3572 +                        ss=oldss; _ss.limit=oldsslimit; _ss.limitw=oldsslimitw;
 40.3573 +                        ssegs=0;
 40.3574 +                }
 40.3575 +                if (abrt)
 40.3576 +                {
 40.3577 +                        tempi = abrt;
 40.3578 +                        abrt = 0;
 40.3579 +                        x86_doabrt(tempi);
 40.3580 +                        if (abrt)
 40.3581 +                        {
 40.3582 +                                abrt = 0;
 40.3583 +                                CS = oldcs;
 40.3584 +                                pc = oldpc;
 40.3585 +                                pclog("Double fault\n");
 40.3586 +//                                dumpregs();
 40.3587 +//                                exit(-1);
 40.3588 +                                pmodeint(8, 0);
 40.3589 +                                if (abrt)
 40.3590 +                                {
 40.3591 +                                        abrt = 0;
 40.3592 +                                        softresetx86();
 40.3593 +                                        pclog("Triple fault - reset\n");
 40.3594 +                                }
 40.3595 +                        }
 40.3596 +                }
 40.3597 +                cycdiff-=cycles;
 40.3598 +
 40.3599 +                pit.c[0]-=cycdiff;
 40.3600 +                pit.c[1]-=cycdiff;
 40.3601 +                if (ppi.pb&1)         pit.c[2]-=cycdiff;
 40.3602 +
 40.3603 +                if ((pit.c[0]<1)||(pit.c[1]<1)||(pit.c[2]<1)) pit_poll();
 40.3604 +
 40.3605 +                spktime-=cycdiff;
 40.3606 +                if (spktime<=0.0)
 40.3607 +                {
 40.3608 +                        spktime+=SPKCONST;
 40.3609 +//                        pclog("1Poll spk\n");
 40.3610 +                        pollspk();
 40.3611 +                        pollgussamp();
 40.3612 +                        getsbsamp();
 40.3613 +                        polladlib();
 40.3614 +                        getdacsamp();
 40.3615 +//                        pclog("2Poll spk\n");
 40.3616 +                }
 40.3617 +                soundtime-=cycdiff;
 40.3618 +                if (soundtime<=0.0)
 40.3619 +                {
 40.3620 +                        soundtime+=SOUNDCONST;
 40.3621 +//                        pclog("1Poll sound60hz\n");
 40.3622 +                        pollsound60hz();
 40.3623 +//                        pclog("2Poll sound60hz\n");
 40.3624 +                }
 40.3625 +                gustime-=cycdiff;
 40.3626 +                while (gustime<=0.0)
 40.3627 +                {
 40.3628 +                        gustime+=GUSCONST;
 40.3629 +                        pollgus();
 40.3630 +                }
 40.3631 +                gustime2-=cycdiff;
 40.3632 +                while (gustime2<=0.0)
 40.3633 +                {
 40.3634 +                        gustime2+=GUSCONST2;
 40.3635 +                        pollgus2();
 40.3636 +                }
 40.3637 +                vidtime-=cycdiff;
 40.3638 +                if (vidtime<=0.0)
 40.3639 +                {
 40.3640 +//                        pclog("1Poll video\n");
 40.3641 +                        pollvideo();
 40.3642 +//                        pclog("2Poll video\n");
 40.3643 +                }
 40.3644 +                if (disctime)
 40.3645 +                {
 40.3646 +                        disctime-=cycdiff/4;
 40.3647 +                        if (disctime<=0)
 40.3648 +                        {
 40.3649 +//                                pclog("1Poll disc\n");
 40.3650 +                                disctime=0;
 40.3651 +                                fdc_poll();
 40.3652 +//                                pclog("2Poll disc\n");
 40.3653 +                        }
 40.3654 +                }
 40.3655 +                if (mousedelay)
 40.3656 +                {
 40.3657 +                        mousedelay-=20;
 40.3658 +                        if (!mousedelay)
 40.3659 +                        {
 40.3660 +//                                pclog("1Poll mouse\n");
 40.3661 +                                mousecallback();
 40.3662 +//                                pclog("2Poll disc\n");
 40.3663 +                        }
 40.3664 +                }
 40.3665 +                if (sbenable)
 40.3666 +                {
 40.3667 +                        sbcount-=cycdiff;
 40.3668 +                        if (sbcount<0)
 40.3669 +                        {
 40.3670 +                                sbcount+=sblatcho;
 40.3671 +                                pollsb();
 40.3672 +                        }
 40.3673 +                }
 40.3674 +                if (sb_enable_i)
 40.3675 +                {
 40.3676 +                        sb_count_i-=cycdiff;
 40.3677 +                        if (sb_count_i<0)
 40.3678 +                        {
 40.3679 +                                sb_count_i+=sblatchi;
 40.3680 +                                sb_poll_i();
 40.3681 +                        }
 40.3682 +                }
 40.3683 +                rtctime-=cycdiff;
 40.3684 +                if (rtctime<0)
 40.3685 +                {
 40.3686 +                        nvr_rtc();
 40.3687 +                }
 40.3688 +                if (idecallback[0])
 40.3689 +                {
 40.3690 +                        idecallback[0]--;
 40.3691 +                        if (idecallback[0]<=0)
 40.3692 +                        {
 40.3693 +//                                pclog("IDE time over\n");
 40.3694 +                                idecallback[0]=0;
 40.3695 +                                callbackide(0);
 40.3696 +                        }
 40.3697 +                }
 40.3698 +                if (idecallback[1])
 40.3699 +                {
 40.3700 +                        idecallback[1]--;
 40.3701 +                        if (idecallback[1]<=0)
 40.3702 +                        {
 40.3703 +//                                pclog("IDE time over\n");
 40.3704 +                                idecallback[1]=0;
 40.3705 +                                callbackide(1);
 40.3706 +                        }
 40.3707 +                }
 40.3708 +                if (trap && (flags&T_FLAG) && !noint)
 40.3709 +                {
 40.3710 +                        if (msw&1)
 40.3711 +                        {
 40.3712 +                                pmodeint(1,0);
 40.3713 +                                cycles -= 40;
 40.3714 +                        }
 40.3715 +                        else
 40.3716 +                        {
 40.3717 +                                writememw(ss,(SP-2)&0xFFFF,flags);
 40.3718 +                                writememw(ss,(SP-4)&0xFFFF,CS);
 40.3719 +                                writememw(ss,(SP-6)&0xFFFF,pc);
 40.3720 +                                SP-=6;
 40.3721 +                                addr=1<<2;
 40.3722 +                                flags&=~I_FLAG;
 40.3723 +                                flags&=~T_FLAG;
 40.3724 +                                pc=readmemw(0,addr);
 40.3725 +                                loadcs(readmemw(0,addr+2));
 40.3726 +                                cycles -= 23;
 40.3727 +                        }
 40.3728 +                }
 40.3729 +                else if ((flags&I_FLAG) && (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)) && !ssegs && !noint)
 40.3730 +                {
 40.3731 +//                        pclog("Test %02X %02X %02X\n", pic.pend, pic.mask, pic.mask2);
 40.3732 +                        temp=picinterrupt();
 40.3733 +                        if (temp!=0xFF)
 40.3734 +                        {
 40.3735 +//                                pclog("286 int %02X %02X %02X %02X\n",temp, pic.pend, pic.mask, pic.mask2);
 40.3736 +                                if (inhlt) pc++;
 40.3737 +//                                intcount++;
 40.3738 +                                if (msw&1)
 40.3739 +                                {
 40.3740 +                                        pmodeint(temp,0);
 40.3741 +                                        cycles -= 40;
 40.3742 +                                }
 40.3743 +                                else
 40.3744 +                                {
 40.3745 +                                        writememw(ss,(SP-2)&0xFFFF,flags);
 40.3746 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
 40.3747 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
 40.3748 +                                        SP-=6;
 40.3749 +                                        addr=temp<<2;
 40.3750 +                                        flags&=~I_FLAG;
 40.3751 +                                        flags&=~T_FLAG;
 40.3752 +                                        pc=readmemw(0,addr);
 40.3753 +                                        loadcs(readmemw(0,addr+2));
 40.3754 +                                        cycles -= 23;
 40.3755 +                                }
 40.3756 +                                inint=1;
 40.3757 +                        }
 40.3758 +                }
 40.3759 +
 40.3760 +/*                if (pc==0xCC32 && es>0x180000)
 40.3761 +                {
 40.3762 +                        pc=0xCBEB;
 40.3763 +//                        output=1;
 40.3764 +//                        timetolive=500000;
 40.3765 +                }*/
 40.3766 +
 40.3767 +                if (noint) noint=0;
 40.3768 +                ins++;
 40.3769 +                insc++;
 40.3770 +                
 40.3771 +//                if (ins == 25000000) output = 3;
 40.3772 +/*                if (timetolive)
 40.3773 +                {
 40.3774 +                        timetolive--;
 40.3775 +                        if (!timetolive)
 40.3776 +                        {
 40.3777 +                                dumpregs();
 40.3778 +                                exit(-1);
 40.3779 +                        } //output=0;
 40.3780 +                }*/
 40.3781 +                keybsenddelay--;
 40.3782 +                if (keybsenddelay<1)
 40.3783 +                {
 40.3784 +                        keybsenddelay = 2500;
 40.3785 +                        keyboard_poll();
 40.3786 +                }
 40.3787 +                //output = 3;
 40.3788 +        }
 40.3789 +}
 40.3790 +//#endif
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/src/386.c	Sun Apr 21 14:54:35 2013 +0100
    41.3 @@ -0,0 +1,8377 @@
    41.4 +//61%
    41.5 +//Win 3.1 - Timer (vtdapi.386) IRQ handler 80020E04 stores to 800200F8
    41.6 +
    41.7 +//11A2D
    41.8 +//3EF08 - SYS_FloatTime()
    41.9 +
   41.10 +#include <stdio.h>
   41.11 +#include <stdint.h>
   41.12 +#include <stdlib.h>
   41.13 +#include "ibm.h"
   41.14 +#include "x86.h"
   41.15 +#include "x87.h"
   41.16 +#include "mem.h"
   41.17 +#include "cpu.h"
   41.18 +#include "fdc.h"
   41.19 +#include "video.h"
   41.20 +
   41.21 +extern int resets;
   41.22 +int gpf = 0;
   41.23 +int ins2 = 0;
   41.24 +
   41.25 +//                        pclog("IO perm fail on %04X\n",port); \
   41.26 +
   41.27 +
   41.28 +#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
   41.29 +                        { \
   41.30 +                                tempi = checkio(port); \
   41.31 +                                if (abrt) break; \
   41.32 +                                if (tempi) \
   41.33 +                                { \
   41.34 +                                        x86gpf(NULL,0); \
   41.35 +                                        break; \
   41.36 +                                } \
   41.37 +                        }
   41.38 +
   41.39 +
   41.40 +int cpl_override=0;
   41.41 +
   41.42 +int has_fpu;
   41.43 +int fpucount=0;
   41.44 +int times;
   41.45 +uint16_t rds;
   41.46 +uint16_t ea_rseg;
   41.47 +
   41.48 +int hitits=0;
   41.49 +
   41.50 +uint32_t oldpc2;
   41.51 +int is486;
   41.52 +int cgate32;
   41.53 +uint8_t opcode2;
   41.54 +int incga;
   41.55 +int enters=0;
   41.56 +int ec;
   41.57 +
   41.58 +uint32_t ten3688;
   41.59 +int oldv86=0,oldpmode=0,itson=0;
   41.60 +uint8_t old22;
   41.61 +#undef readmemb
   41.62 +#undef writememb
   41.63 +
   41.64 +//#define readmemb(s,a) readmemb386l(s,a)
   41.65 +//#define writememb(s,a,v) writememb386l(s,a,v)
   41.66 +
   41.67 +//#define is486 1
   41.68 +
   41.69 +#define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)?readmemb386l(s,a):ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)])
   41.70 +
   41.71 +#define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememb386l(s,a,v); else ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]=v
   41.72 +
   41.73 +#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
   41.74 +#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
   41.75 +
   41.76 +
   41.77 +/*#undef readmemw
   41.78 +#undef readmeml
   41.79 +
   41.80 +#define readmemb(s, a) readmemb386l(s, a)
   41.81 +#define readmemw(s, a) readmemwl(s, a)
   41.82 +#define readmeml(s, a) readmemll(s, a)*/
   41.83 +
   41.84 +/*#define writememb(s,a,v) writememb386l(s, a, v)
   41.85 +#define writememw(s,a,v) writememwl(s, a, v)
   41.86 +#define writememl(s,a,v) writememll(s, a, v)*/
   41.87 +//#define readmemb(s,a)    readmemb((s)+(a))
   41.88 +//#define writememb(s,a,v) writememb((s)+(a),v)
   41.89 +uint32_t mmucache[0x100000];
   41.90 +
   41.91 +uint8_t romext[32768];
   41.92 +uint8_t *ram,*rom,*vram,*vrom;
   41.93 +uint16_t biosmask;
   41.94 +
   41.95 +/*uint16_t getwordx()
   41.96 +{
   41.97 +        pc+=2;
   41.98 +        return readmemw(cs,(pc-2));
   41.99 +}*/
  41.100 +
  41.101 +#define getword() getwordx()
  41.102 +
  41.103 +
  41.104 +//#define readmemb(s,a) readmemb386(s,a)
  41.105 +//#define writememb(s,a,v) writememb386(s,a,v)
  41.106 +
  41.107 +//uint32_t fetchdat;
  41.108 +uint32_t rmdat32;
  41.109 +#define rmdat rmdat32
  41.110 +#define fetchdat rmdat32
  41.111 +uint32_t backupregs[16];
  41.112 +int oddeven=0;
  41.113 +int inttype,abrt;
  41.114 +
  41.115 +
  41.116 +uint32_t oldcs2;
  41.117 +uint32_t oldecx;
  41.118 +uint32_t op32;
  41.119 +
  41.120 +static inline uint16_t fastreadw(uint32_t a)
  41.121 +{
  41.122 +        uint32_t t;
  41.123 +        if ((a&0xFFF)>0xFFE)
  41.124 +        {
  41.125 +                t=readmemb(0,a);
  41.126 +                t|=(readmemb(0,a+1)<<8);
  41.127 +                return t;
  41.128 +        }
  41.129 +        if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
  41.130 +        pccache2=getpccache(a);
  41.131 +        pccache=a>>12;
  41.132 +        return *((uint16_t *)&pccache2[a]);
  41.133 +}
  41.134 +
  41.135 +static inline uint32_t fastreadl(uint32_t a)
  41.136 +{
  41.137 +        uint8_t *t;
  41.138 +        uint32_t val;
  41.139 +        if ((a&0xFFF)<0xFFD)
  41.140 +        {
  41.141 +                if ((a>>12)!=pccache)
  41.142 +                {
  41.143 +                        t = getpccache(a);
  41.144 +                        if (abrt) return 0;
  41.145 +                        pccache2 = t;
  41.146 +                        pccache=a>>12;
  41.147 +                        //return *((uint32_t *)&pccache2[a]);
  41.148 +                }
  41.149 +                return *((uint32_t *)&pccache2[a]);
  41.150 +        }
  41.151 +        val  =readmemb(0,a);
  41.152 +        val |=(readmemb(0,a+1)<<8);
  41.153 +        val |=(readmemb(0,a+2)<<16);
  41.154 +        val |=(readmemb(0,a+3)<<24);
  41.155 +        return val;
  41.156 +}
  41.157 +
  41.158 +static inline uint16_t getword()
  41.159 +{
  41.160 +        pc+=2;
  41.161 +        return fastreadw(cs+(pc-2));
  41.162 +}
  41.163 +
  41.164 +static inline uint32_t getlong()
  41.165 +{
  41.166 +        pc+=4;
  41.167 +        return fastreadl(cs+(pc-4));
  41.168 +}
  41.169 +
  41.170 +uint32_t *eal_r, *eal_w;
  41.171 +static inline uint8_t geteab()
  41.172 +{
  41.173 +        if (mod==3)
  41.174 +           return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
  41.175 +        if (eal_r) return *(uint8_t *)eal_r;
  41.176 +        return readmemb(easeg,eaaddr);
  41.177 +}
  41.178 +
  41.179 +static inline uint16_t geteaw()
  41.180 +{
  41.181 +        if (mod==3)
  41.182 +           return regs[rm].w;
  41.183 +//        cycles-=3;
  41.184 +        if (eal_r) return *(uint16_t *)eal_r;
  41.185 +        return readmemw(easeg,eaaddr);
  41.186 +}
  41.187 +
  41.188 +static inline uint32_t geteal()
  41.189 +{
  41.190 +        if (mod==3)
  41.191 +           return regs[rm].l;
  41.192 +//        cycles-=3;
  41.193 +        if (eal_r) return *eal_r;
  41.194 +        return readmeml(easeg,eaaddr);
  41.195 +}
  41.196 +
  41.197 +#define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v;  else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v
  41.198 +#define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v);    } else regs[rm].w=v
  41.199 +#define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v;             else writememll(easeg,eaaddr,v);    } else regs[rm].l=v
  41.200 +
  41.201 +static inline void fetcheal32sib()
  41.202 +{
  41.203 +        uint8_t sib;
  41.204 +        sib=rmdat>>8;// pc++;
  41.205 +        switch (mod)
  41.206 +        {
  41.207 +                case 0: eaaddr=regs[sib&7].l; pc++; break;
  41.208 +                case 1: eaaddr=((uint32_t)(int8_t)(rmdat>>16))+regs[sib&7].l; pc+=2; break;
  41.209 +                case 2: eaaddr=(fastreadl(cs+pc+1))+regs[sib&7].l; pc+=5; break;
  41.210 +        }
  41.211 +        /*SIB byte present*/
  41.212 +        if ((sib&7)==5 && !mod) eaaddr=getlong();
  41.213 +        else if ((sib&6)==4)
  41.214 +        {
  41.215 +                easeg=ss;
  41.216 +                ea_rseg=SS;
  41.217 +        }
  41.218 +        if (((sib>>3)&7)!=4) eaaddr+=regs[(sib>>3)&7].l<<(sib>>6);
  41.219 +}
  41.220 +
  41.221 +static inline void fetcheal32nosib()
  41.222 +{
  41.223 +        if (rm==5)
  41.224 +        {
  41.225 +                easeg=ss;
  41.226 +                ea_rseg=SS;
  41.227 +        }
  41.228 +        if (mod==1) { eaaddr+=((uint32_t)(int8_t)(rmdat>>8)); pc++; }
  41.229 +        else        { eaaddr+=getlong(); }
  41.230 +}
  41.231 +
  41.232 +uint16_t *mod1add[2][8];
  41.233 +uint32_t *mod1seg[8];
  41.234 +
  41.235 +void fetchea32()
  41.236 +{
  41.237 +        eal_r = eal_w = NULL;
  41.238 +        if (op32&0x200)
  41.239 +        {
  41.240 +                /*rmdat=readmemw(cs,pc); */pc++;
  41.241 +                reg=(rmdat>>3)&7;
  41.242 +                mod=(rmdat>>6)&3;
  41.243 +                rm=rmdat&7;
  41.244 +                
  41.245 +                if (mod!=3)
  41.246 +                {
  41.247 +                        easeg=ds;
  41.248 +                        ea_rseg=DS;
  41.249 +                        if (rm==4)      fetcheal32sib();
  41.250 +                        else
  41.251 +                        {
  41.252 +                                eaaddr=regs[rm].l;
  41.253 +                                if (mod) fetcheal32nosib();
  41.254 +                                else if (rm==5) eaaddr=getlong();
  41.255 +                        }
  41.256 +                        if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
  41.257 +                        {
  41.258 +                                if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
  41.259 +                                   eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)];
  41.260 +                                if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
  41.261 +                                   eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)];
  41.262 +                        }
  41.263 +                }
  41.264 +        }
  41.265 +        else
  41.266 +        {
  41.267 +                /*rmdat=readmemb(cs,pc); */pc++;
  41.268 +                reg=(rmdat>>3)&7;
  41.269 +                mod=(rmdat>>6)&3;
  41.270 +                rm=rmdat&7;
  41.271 +                if (mod!=3)
  41.272 +                {
  41.273 +                        if (!mod && rm==6) { eaaddr=(rmdat>>8)&0xFFFF; pc+=2; easeg=ds; ea_rseg=DS; }
  41.274 +                        else
  41.275 +                        {
  41.276 +                                switch (mod)
  41.277 +                                {
  41.278 +                                        case 0:
  41.279 +                                        eaaddr=0;
  41.280 +                                        break;
  41.281 +                                        case 1:
  41.282 +                                        eaaddr=(uint16_t)(int8_t)(rmdat>>8); pc++;
  41.283 +                                        break;
  41.284 +                                        case 2:
  41.285 +                                        eaaddr=getword();
  41.286 +                                        break;
  41.287 +                                }
  41.288 +                                eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]);
  41.289 +                                easeg=*mod1seg[rm];
  41.290 +                                if (mod1seg[rm]==&ss) ea_rseg=SS;
  41.291 +                                else                  ea_rseg=DS;
  41.292 +                                eaaddr&=0xFFFF;
  41.293 +                        }
  41.294 +                        if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
  41.295 +                        {
  41.296 +                                if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
  41.297 +                                   eal_r = (uint32_t *)&ram[ readlookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)];
  41.298 +                                if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
  41.299 +                                   eal_w = (uint32_t *)&ram[writelookup2[(easeg + eaaddr) >> 12] + ((easeg + eaaddr) & 0xFFF)];
  41.300 +                        }
  41.301 +/*                        if (readlookup2[(easeg+eaaddr)>>12]!=0xFFFFFFFF && easeg!=0xFFFFFFFF && ((easeg+eaaddr)&0xFFF)<=0xFFC)
  41.302 +                           eal=(uint32_t *)&ram[readlookup2[(easeg+eaaddr)>>12]+((easeg+eaaddr)&0xFFF)];*/
  41.303 +                }
  41.304 +        }
  41.305 +}
  41.306 +
  41.307 +#undef fetchea
  41.308 +#define fetchea() fetchea32(); if (abrt) break
  41.309 +#define fetchea2() rmdat=fastreadl(cs+pc); fetchea32(); if (abrt) break
  41.310 +
  41.311 +#include "x86_flags.h"
  41.312 +
  41.313 +void setadd32(uint32_t a, uint32_t b)
  41.314 +{
  41.315 +        uint32_t c=(uint32_t)a+(uint32_t)b;
  41.316 +        flags&=~0x8D5;
  41.317 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.318 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.319 +        if (c<a) flags|=C_FLAG;
  41.320 +        if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG;
  41.321 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
  41.322 +}
  41.323 +void setadd32nc(uint32_t a, uint32_t b)
  41.324 +{
  41.325 +        uint32_t c=(uint32_t)a+(uint32_t)b;
  41.326 +        flags&=~0x8D4;
  41.327 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.328 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.329 +        if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG;
  41.330 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
  41.331 +}
  41.332 +void setadc32(uint32_t a, uint32_t b)
  41.333 +{
  41.334 +        uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
  41.335 +        flags&=~0x8D5;
  41.336 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.337 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.338 +        if ((c<a) || (c==a && tempc)) flags|=C_FLAG;
  41.339 +        if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG;
  41.340 +        if (((a&0xF)+(b&0xF)+tempc)&0x10)      flags|=A_FLAG;
  41.341 +}
  41.342 +void setsub32(uint32_t a, uint32_t b)
  41.343 +{
  41.344 +        uint32_t c=(uint32_t)a-(uint32_t)b;
  41.345 +        flags&=~0x8D5;
  41.346 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.347 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.348 +        if (c>a) flags|=C_FLAG;
  41.349 +        if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG;
  41.350 +        if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
  41.351 +}
  41.352 +void setsub32nc(uint32_t a, uint32_t b)
  41.353 +{
  41.354 +        uint32_t c=(uint32_t)a-(uint32_t)b;
  41.355 +        flags&=~0x8D4;
  41.356 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.357 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.358 +        if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG;
  41.359 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
  41.360 +}
  41.361 +void setsbc32(uint32_t a, uint32_t b)
  41.362 +{
  41.363 +        uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
  41.364 +        flags&=~0x8D5;
  41.365 +        flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
  41.366 +        flags|=(znptable8[c&0xFF]&P_FLAG);
  41.367 +        if ((c>a) || (c==a && tempc)) flags|=C_FLAG;
  41.368 +        if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG;
  41.369 +        if (((a&0xF)-((b&0xF)+tempc))&0x10)      flags|=A_FLAG;
  41.370 +}
  41.371 +
  41.372 +
  41.373 +
  41.374 +void x86_int(int num)
  41.375 +{
  41.376 +        uint32_t addr;
  41.377 +                                pc=oldpc;
  41.378 +                                if (msw&1)
  41.379 +                                {
  41.380 +                                        pmodeint(num,0);
  41.381 +                                }
  41.382 +                                else
  41.383 +                                {
  41.384 +                                        if (ssegs) ss=oldss;
  41.385 +                                        if (stack32)
  41.386 +                                        {
  41.387 +                                                writememw(ss,ESP-2,flags);
  41.388 +                                                writememw(ss,ESP-4,CS);
  41.389 +                                                writememw(ss,ESP-6,pc);
  41.390 +                                                ESP-=6;
  41.391 +                                        }
  41.392 +                                        else
  41.393 +                                        {
  41.394 +                                                writememw(ss,((SP-2)&0xFFFF),flags);
  41.395 +                                                writememw(ss,((SP-4)&0xFFFF),CS);
  41.396 +                                                writememw(ss,((SP-6)&0xFFFF),pc);
  41.397 +                                                SP-=6;
  41.398 +                                        }
  41.399 +                                        addr=num<<2;
  41.400 +
  41.401 +                                        flags&=~I_FLAG;
  41.402 +                                        flags&=~T_FLAG;
  41.403 +                                        oxpc=pc;
  41.404 +                                        pc=readmemw(0,addr);
  41.405 +                                        loadcs(readmemw(0,addr+2));
  41.406 +                                }
  41.407 +                                cycles-=70;
  41.408 +}
  41.409 +
  41.410 +#define NOTRM   if (!(msw & 1) || (eflags & VM_FLAG))\
  41.411 +                { \
  41.412 +                        x86_int(6); \
  41.413 +                        break; \
  41.414 +                }
  41.415 +
  41.416 +void rep386(int fv)
  41.417 +{
  41.418 +        uint8_t temp;
  41.419 +        uint32_t c;//=CX;
  41.420 +        uint8_t temp2;
  41.421 +        uint16_t tempw,tempw2,tempw3,of=flags;
  41.422 +        uint32_t ipc=oldpc;//pc-1;
  41.423 +        int changeds=0;
  41.424 +        uint32_t oldds;
  41.425 +        uint32_t rep32=op32;
  41.426 +        uint32_t templ,templ2;
  41.427 +        int tempz;
  41.428 +        int tempi;
  41.429 +//        if (output) pclog("REP32 %04X %04X  ",use32,rep32);
  41.430 +        startrep:
  41.431 +        temp=opcode2=readmemb(cs,pc); pc++;
  41.432 +//        if (firstrepcycle && temp==0xA5) pclog("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
  41.433 +//        if (output) pclog("REP %02X %04X\n",temp,ipc);
  41.434 +        c=(rep32&0x200)?ECX:CX;
  41.435 +/*        if (rep32 && (msw&1))
  41.436 +        {
  41.437 +                if (temp!=0x67 && temp!=0x66 && (rep32|temp)!=0x1AB && (rep32|temp)!=0x3AB) pclog("32-bit REP %03X %08X %04X:%06X\n",temp|rep32,c,CS,pc);
  41.438 +        }*/
  41.439 +        switch (temp|rep32)
  41.440 +        {
  41.441 +                case 0xC3: case 0x1C3: case 0x2C3: case 0x3C3:
  41.442 +                pc--;
  41.443 +                break;
  41.444 +                case 0x08:
  41.445 +                pc=ipc+1;
  41.446 +                break;
  41.447 +                case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/
  41.448 +                oldds=ds;
  41.449 +                ds=es;
  41.450 +                rds=ES;
  41.451 +                changeds=1;
  41.452 +                goto startrep;
  41.453 +                break;
  41.454 +                case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/
  41.455 +                oldds=ds;
  41.456 +                ds=cs;
  41.457 +                rds=CS;
  41.458 +                changeds=1;
  41.459 +                goto startrep;
  41.460 +                break;
  41.461 +                case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/
  41.462 +                oldds=ds;
  41.463 +                ds=ss;
  41.464 +                rds=SS;
  41.465 +                changeds=1;
  41.466 +                goto startrep;
  41.467 +                break;
  41.468 +                case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/
  41.469 +                oldds=ds;
  41.470 +                ds=ds;
  41.471 +                changeds=1;
  41.472 +                goto startrep;
  41.473 +                break;
  41.474 +                case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/
  41.475 +                oldds=ds;
  41.476 +                ds=fs;
  41.477 +                rds=FS;
  41.478 +                changeds=1;
  41.479 +                goto startrep;
  41.480 +                case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/
  41.481 +                oldds=ds;
  41.482 +                ds=gs;
  41.483 +                rds=GS;
  41.484 +                changeds=1;
  41.485 +                goto startrep;
  41.486 +                case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/
  41.487 +                rep32^=0x100;
  41.488 +                goto startrep;
  41.489 +                case 0x67: case 0x167: case 0x267: case 0x367:  /*Address size prefix*/
  41.490 +                rep32^=0x200;
  41.491 +                goto startrep;
  41.492 +                case 0x6C: case 0x16C: /*REP INSB*/
  41.493 +                if (c>0)
  41.494 +                {
  41.495 +                        checkio_perm(DX);
  41.496 +                        temp2=inb(DX);
  41.497 +                        writememb(es,DI,temp2);
  41.498 +                        if (abrt) break;
  41.499 +                        if (flags&D_FLAG) DI--;
  41.500 +                        else              DI++;
  41.501 +                        c--;
  41.502 +                        cycles-=15;
  41.503 +                }
  41.504 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.505 +                else firstrepcycle=1;
  41.506 +                break;
  41.507 +                case 0x26C: case 0x36C: /*REP INSB*/
  41.508 +                if (c>0)
  41.509 +                {
  41.510 +                        checkio_perm(DX);
  41.511 +                        temp2=inb(DX);
  41.512 +                        writememb(es,EDI,temp2);
  41.513 +                        if (abrt) break;
  41.514 +                        if (flags&D_FLAG) EDI--;
  41.515 +                        else              EDI++;
  41.516 +                        c--;
  41.517 +                        cycles-=15;
  41.518 +                }
  41.519 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.520 +                else firstrepcycle=1;
  41.521 +                break;
  41.522 +                case 0x6D: /*REP INSW*/
  41.523 +                if (c>0)
  41.524 +                {
  41.525 +                        tempw=inw(DX);
  41.526 +                        writememw(es,DI,tempw);
  41.527 +                        if (abrt) break;
  41.528 +                        if (flags&D_FLAG) DI-=2;
  41.529 +                        else              DI+=2;
  41.530 +                        c--;
  41.531 +                        cycles-=15;
  41.532 +                }
  41.533 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.534 +                else firstrepcycle=1;
  41.535 +                break;
  41.536 +                case 0x16D: /*REP INSL*/
  41.537 +                if (c>0)
  41.538 +                {
  41.539 +                        templ=inl(DX);
  41.540 +                        writememl(es,DI,templ);
  41.541 +                        if (abrt) break;
  41.542 +                        if (flags&D_FLAG) DI-=4;
  41.543 +                        else              DI+=4;
  41.544 +                        c--;
  41.545 +                        cycles-=15;
  41.546 +                }
  41.547 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.548 +                else firstrepcycle=1;
  41.549 +                break;
  41.550 +                case 0x26D: /*REP INSW*/
  41.551 +                if (c>0)
  41.552 +                {
  41.553 +                        tempw=inw(DX);
  41.554 +                        writememw(es,EDI,tempw);
  41.555 +                        if (abrt) break;
  41.556 +                        if (flags&D_FLAG) EDI-=2;
  41.557 +                        else              EDI+=2;
  41.558 +                        c--;
  41.559 +                        cycles-=15;
  41.560 +                }
  41.561 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.562 +                else firstrepcycle=1;
  41.563 +                break;
  41.564 +                case 0x36D: /*REP INSL*/
  41.565 +                if (c>0)
  41.566 +                {
  41.567 +                        templ=inl(DX);
  41.568 +                        writememl(es,EDI,templ);
  41.569 +                        if (abrt) break;
  41.570 +                        if (flags&D_FLAG) EDI-=4;
  41.571 +                        else              EDI+=4;
  41.572 +                        c--;
  41.573 +                        cycles-=15;
  41.574 +                }
  41.575 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.576 +                else firstrepcycle=1;
  41.577 +                break;
  41.578 +                case 0x6E: case 0x16E: /*REP OUTSB*/
  41.579 +                if (c>0)
  41.580 +                {
  41.581 +                        temp2=readmemb(ds,SI);
  41.582 +                        if (abrt) break;
  41.583 +                        checkio_perm(DX);
  41.584 +                        outb(DX,temp2);
  41.585 +                        if (flags&D_FLAG) SI--;
  41.586 +                        else              SI++;
  41.587 +                        c--;
  41.588 +                        cycles-=14;
  41.589 +                }
  41.590 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.591 +                else firstrepcycle=1;
  41.592 +                break;
  41.593 +                case 0x26E: case 0x36E: /*REP OUTSB*/
  41.594 +                if (c>0)
  41.595 +                {
  41.596 +                        temp2=readmemb(ds,ESI);
  41.597 +                        if (abrt) break;
  41.598 +                        checkio_perm(DX);
  41.599 +                        outb(DX,temp2);
  41.600 +                        if (flags&D_FLAG) ESI--;
  41.601 +                        else              ESI++;
  41.602 +                        c--;
  41.603 +                        cycles-=14;
  41.604 +                }
  41.605 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.606 +                else firstrepcycle=1;
  41.607 +                break;
  41.608 +                case 0x6F: /*REP OUTSW*/
  41.609 +                if (c>0)
  41.610 +                {
  41.611 +                        tempw=readmemw(ds,SI);
  41.612 +                        if (abrt) break;
  41.613 +//                        pclog("OUTSW %04X -> %04X\n",SI,tempw);
  41.614 +                        outw(DX,tempw);
  41.615 +                        if (flags&D_FLAG) SI-=2;
  41.616 +                        else              SI+=2;
  41.617 +                        c--;
  41.618 +                        cycles-=14;
  41.619 +                }
  41.620 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.621 +                else firstrepcycle=1;
  41.622 +                break;
  41.623 +                case 0x16F: /*REP OUTSL*/
  41.624 +                if (c > 0)
  41.625 +                {
  41.626 +                        templ = readmeml(ds, SI);
  41.627 +                        if (abrt) break;
  41.628 +                        outl(DX, templ);
  41.629 +                        if (flags & D_FLAG) SI -= 4;
  41.630 +                        else                SI += 4;
  41.631 +                        c--;
  41.632 +                        cycles -= 14;
  41.633 +                }
  41.634 +                if (c > 0) { firstrepcycle = 0; pc = ipc; if (ssegs) ssegs++; }
  41.635 +                else firstrepcycle = 1;
  41.636 +                break;
  41.637 +                case 0x26F: /*REP OUTSW*/
  41.638 +                if (c>0)
  41.639 +                {
  41.640 +                        tempw=readmemw(ds,ESI);
  41.641 +                        if (abrt) break;
  41.642 +                        outw(DX,tempw);
  41.643 +                        if (flags&D_FLAG) ESI-=2;
  41.644 +                        else              ESI+=2;
  41.645 +                        c--;
  41.646 +                        cycles-=14;
  41.647 +                }
  41.648 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.649 +                else firstrepcycle=1;
  41.650 +                break;
  41.651 +                case 0x36F: /*REP OUTSL*/
  41.652 +                if (c > 0)
  41.653 +                {
  41.654 +                        templ = readmeml(ds, ESI);
  41.655 +                        if (abrt) break;
  41.656 +                        outl(DX, templ);
  41.657 +                        if (flags & D_FLAG) ESI -= 4;
  41.658 +                        else                ESI += 4;
  41.659 +                        c--;
  41.660 +                        cycles -= 14;
  41.661 +                }
  41.662 +                if (c > 0) { firstrepcycle = 0; pc = ipc; if (ssegs) ssegs++; }
  41.663 +                else firstrepcycle = 1;
  41.664 +                break;
  41.665 +                case 0xA4: case 0x1A4: /*REP MOVSB*/
  41.666 +                if (c>0)
  41.667 +                {
  41.668 +                        temp2=readmemb(ds,SI);  if (abrt) break;
  41.669 +                        writememb(es,DI,temp2); if (abrt) break;
  41.670 +//                        if (output==3) pclog("MOVSB %08X:%04X -> %08X:%04X %02X\n",ds,SI,es,DI,temp2);
  41.671 +                        if (flags&D_FLAG) { DI--; SI--; }
  41.672 +                        else              { DI++; SI++; }
  41.673 +                        c--;
  41.674 +                        cycles-=(is486)?3:4;
  41.675 +                }
  41.676 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.677 +                else firstrepcycle=1;
  41.678 +                break;
  41.679 +                case 0x2A4: case 0x3A4: /*REP MOVSB*/
  41.680 +                if (c>0)
  41.681 +                {
  41.682 +                        temp2=readmemb(ds,ESI);  if (abrt) break;
  41.683 +                        writememb(es,EDI,temp2); if (abrt) break;
  41.684 +                        if (flags&D_FLAG) { EDI--; ESI--; }
  41.685 +                        else              { EDI++; ESI++; }
  41.686 +                        c--;
  41.687 +                        cycles-=(is486)?3:4;
  41.688 +                }
  41.689 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.690 +                else firstrepcycle=1;
  41.691 +                break;
  41.692 +                case 0xA5: /*REP MOVSW*/
  41.693 +                if (c>0)
  41.694 +                {
  41.695 +                        tempw=readmemw(ds,SI);  if (abrt) break;
  41.696 +                        writememw(es,DI,tempw); if (abrt) break;
  41.697 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
  41.698 +                        else              { DI+=2; SI+=2; }
  41.699 +                        c--;
  41.700 +                        cycles-=(is486)?3:4;
  41.701 +                }
  41.702 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.703 +                else firstrepcycle=1;
  41.704 +                break;
  41.705 +                case 0x1A5: /*REP MOVSL*/
  41.706 +                if (c>0)
  41.707 +                {
  41.708 +                        templ=readmeml(ds,SI);  if (abrt) break;
  41.709 +//                        pclog("MOVSD %08X from %08X to %08X (%04X:%08X)\n", templ, ds+SI, es+DI, CS, pc);
  41.710 +                        writememl(es,DI,templ); if (abrt) break;
  41.711 +                        if (flags&D_FLAG) { DI-=4; SI-=4; }
  41.712 +                        else              { DI+=4; SI+=4; }
  41.713 +                        c--;
  41.714 +                        cycles-=(is486)?3:4;
  41.715 +                }
  41.716 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.717 +                else firstrepcycle=1;
  41.718 +                break;
  41.719 +                case 0x2A5: /*REP MOVSW*/
  41.720 +                if (c>0)
  41.721 +                {
  41.722 +                        tempw=readmemw(ds,ESI);  if (abrt) break;
  41.723 +                        writememw(es,EDI,tempw); if (abrt) break;
  41.724 +//                        if (output) pclog("Written %04X from %08X to %08X %i  %08X %04X %08X %04X\n",tempw,ds+ESI,es+EDI,c,ds,ES,es,ES);
  41.725 +                        if (flags&D_FLAG) { EDI-=2; ESI-=2; }
  41.726 +                        else              { EDI+=2; ESI+=2; }
  41.727 +                        c--;
  41.728 +                        cycles-=(is486)?3:4;
  41.729 +                }
  41.730 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.731 +                else firstrepcycle=1;
  41.732 +                break;
  41.733 +                case 0x3A5: /*REP MOVSL*/
  41.734 +                if (c>0)
  41.735 +                {
  41.736 +                        templ=readmeml(ds,ESI); if (abrt) break;
  41.737 +//                        if ((EDI&0xFFFF0000)==0xA0000) cycles-=12;
  41.738 +                        writememl(es,EDI,templ); if (abrt) break;
  41.739 +//                        if (output) pclog("Load %08X from %08X to %08X  %04X %08X  %04X %08X\n",templ,ESI,EDI,DS,ds,ES,es);
  41.740 +                        if (flags&D_FLAG) { EDI-=4; ESI-=4; }
  41.741 +                        else              { EDI+=4; ESI+=4; }
  41.742 +                        c--;
  41.743 +                        cycles-=(is486)?3:4;
  41.744 +                }
  41.745 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.746 +                else firstrepcycle=1;
  41.747 +                break;
  41.748 +                case 0xA6: case 0x1A6: /*REP CMPSB*/
  41.749 +                if (fv) flags|=Z_FLAG;
  41.750 +                else    flags&=~Z_FLAG;
  41.751 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.752 +                {
  41.753 +                        temp=readmemb(ds,SI);
  41.754 +                        temp2=readmemb(es,DI);
  41.755 +                        if (abrt) { flags=of; break; }
  41.756 +                        if (flags&D_FLAG) { DI--; SI--; }
  41.757 +                        else              { DI++; SI++; }
  41.758 +                        c--;
  41.759 +                        cycles-=(is486)?7:9;
  41.760 +                        setsub8(temp,temp2);
  41.761 +                }
  41.762 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.763 +                else firstrepcycle=1;
  41.764 +                break;
  41.765 +                case 0x2A6: case 0x3A6: /*REP CMPSB*/
  41.766 +                if (fv) flags|=Z_FLAG;
  41.767 +                else    flags&=~Z_FLAG;
  41.768 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.769 +                {
  41.770 +                        temp=readmemb(ds,ESI);
  41.771 +                        temp2=readmemb(es,EDI);
  41.772 +                        if (abrt) { flags=of; break; }
  41.773 +                        if (flags&D_FLAG) { EDI--; ESI--; }
  41.774 +                        else              { EDI++; ESI++; }
  41.775 +                        c--;
  41.776 +                        cycles-=(is486)?7:9;
  41.777 +                        setsub8(temp,temp2);
  41.778 +                }
  41.779 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.780 +                else firstrepcycle=1;
  41.781 +                break;
  41.782 +                case 0xA7: /*REP CMPSW*/
  41.783 +                if (fv) flags|=Z_FLAG;
  41.784 +                else    flags&=~Z_FLAG;
  41.785 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.786 +                {
  41.787 +//                        pclog("CMPSW %05X %05X  %08X %08X   ", ds+SI, es+DI, readlookup2[(ds+SI)>>12], readlookup2[(es+DI)>>12]);
  41.788 +                        tempw=readmemw(ds,SI);
  41.789 +                        tempw2=readmemw(es,DI);
  41.790 +//                        pclog("%04X %04X %02X\n", tempw, tempw2, ram[8]);
  41.791 +
  41.792 +                        if (abrt) { flags=of; break; }
  41.793 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
  41.794 +                        else              { DI+=2; SI+=2; }
  41.795 +                        c--;
  41.796 +                        cycles-=(is486)?7:9;
  41.797 +                        setsub16(tempw,tempw2);
  41.798 +                }
  41.799 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.800 +                else firstrepcycle=1;
  41.801 +                break;
  41.802 +                case 0x1A7: /*REP CMPSL*/
  41.803 +                if (fv) flags|=Z_FLAG;
  41.804 +                else    flags&=~Z_FLAG;
  41.805 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.806 +                {
  41.807 +                        templ=readmeml(ds,SI);
  41.808 +                        templ2=readmeml(es,DI);
  41.809 +                        if (abrt) { flags=of; break; }
  41.810 +                        if (flags&D_FLAG) { DI-=4; SI-=4; }
  41.811 +                        else              { DI+=4; SI+=4; }
  41.812 +                        c--;
  41.813 +                        cycles-=(is486)?7:9;
  41.814 +                        setsub32(templ,templ2);
  41.815 +                }
  41.816 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.817 +                else firstrepcycle=1;
  41.818 +                break;
  41.819 +                case 0x2A7: /*REP CMPSW*/
  41.820 +                if (fv) flags|=Z_FLAG;
  41.821 +                else    flags&=~Z_FLAG;
  41.822 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.823 +                {
  41.824 +                        tempw=readmemw(ds,ESI);
  41.825 +                        tempw2=readmemw(es,EDI);
  41.826 +                        if (abrt) { flags=of; break; }
  41.827 +                        if (flags&D_FLAG) { EDI-=2; ESI-=2; }
  41.828 +                        else              { EDI+=2; ESI+=2; }
  41.829 +                        c--;
  41.830 +                        cycles-=(is486)?7:9;
  41.831 +                        setsub16(tempw,tempw2);
  41.832 +                }
  41.833 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.834 +                else firstrepcycle=1;
  41.835 +                break;
  41.836 +                case 0x3A7: /*REP CMPSL*/
  41.837 +                if (fv) flags|=Z_FLAG;
  41.838 +                else    flags&=~Z_FLAG;
  41.839 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
  41.840 +                {
  41.841 +                        templ=readmeml(ds,ESI);
  41.842 +                        templ2=readmeml(es,EDI);
  41.843 +                        if (abrt) { flags=of; break; }
  41.844 +                        if (flags&D_FLAG) { EDI-=4; ESI-=4; }
  41.845 +                        else              { EDI+=4; ESI+=4; }
  41.846 +                        c--;
  41.847 +                        cycles-=(is486)?7:9;
  41.848 +                        setsub32(templ,templ2);
  41.849 +                }
  41.850 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
  41.851 +                else firstrepcycle=1;
  41.852 +                break;
  41.853 +
  41.854 +                case 0xAA: case 0x1AA: /*REP STOSB*/
  41.855 +                if (c>0)
  41.856 +                {
  41.857 +                        writememb(es,DI,AL);
  41.858 +                        if (abrt) break;
  41.859 +                        if (flags&D_FLAG) DI--;
  41.860 +                        else              DI++;
  41.861 +                        c--;
  41.862 +                        cycles-=(is486)?4:5;
  41.863 +                }
  41.864 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.865 +                else firstrepcycle=1;
  41.866 +                break;
  41.867 +                case 0x2AA: case 0x3AA: /*REP STOSB*/
  41.868 +                if (c>0)
  41.869 +                {
  41.870 +                        writememb(es,EDI,AL);
  41.871 +                        if (abrt) break;
  41.872 +                        if (flags&D_FLAG) EDI--;
  41.873 +                        else              EDI++;
  41.874 +                        c--;
  41.875 +                        cycles-=(is486)?4:5;
  41.876 +                }
  41.877 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.878 +                else firstrepcycle=1;
  41.879 +                break;
  41.880 +                case 0xAB: /*REP STOSW*/
  41.881 +                if (c>0)
  41.882 +                {
  41.883 +                        writememw(es,DI,AX);
  41.884 +                        if (abrt) break;
  41.885 +                        if (flags&D_FLAG) DI-=2;
  41.886 +                        else              DI+=2;
  41.887 +                        c--;
  41.888 +                        cycles-=(is486)?4:5;
  41.889 +                }
  41.890 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.891 +                else firstrepcycle=1;
  41.892 +                break;
  41.893 +                case 0x2AB: /*REP STOSW*/
  41.894 +                if (c>0)
  41.895 +                {
  41.896 +                        writememw(es,EDI,AX);
  41.897 +                        if (abrt) break;
  41.898 +                        if (flags&D_FLAG) EDI-=2;
  41.899 +                        else              EDI+=2;
  41.900 +                        c--;
  41.901 +                        cycles-=(is486)?4:5;
  41.902 +                }
  41.903 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.904 +                else firstrepcycle=1;
  41.905 +                break;
  41.906 +                case 0x1AB: /*REP STOSL*/
  41.907 +                if (c>0)
  41.908 +                {
  41.909 +                        writememl(es,DI,EAX);
  41.910 +                        if (abrt) break;
  41.911 +                        if (flags&D_FLAG) DI-=4;
  41.912 +                        else              DI+=4;
  41.913 +                        c--;
  41.914 +                        cycles-=(is486)?4:5;
  41.915 +                }
  41.916 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.917 +                else firstrepcycle=1;
  41.918 +                break;
  41.919 +                case 0x3AB: /*REP STOSL*/
  41.920 +                if (c>0)
  41.921 +                {
  41.922 +                        writememl(es,EDI,EAX);
  41.923 +                        if (abrt) break;
  41.924 +                        if (flags&D_FLAG) EDI-=4;
  41.925 +                        else              EDI+=4;
  41.926 +                        c--;
  41.927 +                        cycles-=(is486)?4:5;
  41.928 +                }
  41.929 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.930 +                else firstrepcycle=1;
  41.931 +                break;
  41.932 +                case 0xAC: case 0x1AC: /*REP LODSB*/
  41.933 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
  41.934 +                if (c>0)
  41.935 +                {
  41.936 +                        AL=readmemb(ds,SI);
  41.937 +                        if (abrt) break;
  41.938 +                        if (flags&D_FLAG) SI--;
  41.939 +                        else              SI++;
  41.940 +                        c--;
  41.941 +                        cycles-=5;
  41.942 +                }
  41.943 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.944 +                else firstrepcycle=1;
  41.945 +                break;
  41.946 +                case 0x2AC: case 0x3AC: /*REP LODSB*/
  41.947 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
  41.948 +                if (c>0)
  41.949 +                {
  41.950 +                        AL=readmemb(ds,ESI);
  41.951 +                        if (abrt) break;
  41.952 +                        if (flags&D_FLAG) ESI--;
  41.953 +                        else              ESI++;
  41.954 +                        c--;
  41.955 +                        cycles-=5;
  41.956 +                }
  41.957 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.958 +                else firstrepcycle=1;
  41.959 +                break;
  41.960 +                case 0xAD: /*REP LODSW*/
  41.961 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
  41.962 +                if (c>0)
  41.963 +                {
  41.964 +                        AX=readmemw(ds,SI);
  41.965 +                        if (abrt) break;
  41.966 +                        if (flags&D_FLAG) SI-=2;
  41.967 +                        else              SI+=2;
  41.968 +                        c--;
  41.969 +                        cycles-=5;
  41.970 +                }
  41.971 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.972 +                else firstrepcycle=1;
  41.973 +                break;
  41.974 +                case 0x1AD: /*REP LODSL*/
  41.975 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
  41.976 +                if (c>0)
  41.977 +                {
  41.978 +                        EAX=readmeml(ds,SI);
  41.979 +                        if (abrt) break;
  41.980 +                        if (flags&D_FLAG) SI-=4;
  41.981 +                        else              SI+=4;
  41.982 +                        c--;
  41.983 +                        cycles-=5;
  41.984 +                }
  41.985 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
  41.986 +                else firstrepcycle=1;
  41.987 +                break;
  41.988 +                case 0x2AD: /*REP LODSW*/
  41.989 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
  41.990 +                if (c>0)
  41.991 +                {
  41.992 +                        AX=readmemw(ds,ESI);
  41.993 +                        if (abrt) break;
  41.994 +                        if (flags&D_FLAG) ESI-=2;
  41.995 +                        else              ESI+=2;
  41.996 +                        c--;
  41.997 +                        cycles-=5;
  41.998 +                }
  41.999 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
 41.1000 +                else firstrepcycle=1;
 41.1001 +                break;
 41.1002 +                case 0x3AD: /*REP LODSL*/
 41.1003 +//                if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
 41.1004 +                if (c>0)
 41.1005 +                {
 41.1006 +                        EAX=readmeml(ds,ESI);
 41.1007 +                        if (abrt) break;
 41.1008 +                        if (flags&D_FLAG) ESI-=4;
 41.1009 +                        else              ESI+=4;
 41.1010 +                        c--;
 41.1011 +                        cycles-=5;
 41.1012 +                }
 41.1013 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
 41.1014 +                else firstrepcycle=1;
 41.1015 +                break;
 41.1016 +                case 0xAE: case 0x1AE: /*REP SCASB*/
 41.1017 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc);
 41.1018 +//                tempz=(fv)?1:0;
 41.1019 +                if (fv) flags|=Z_FLAG;
 41.1020 +                else    flags&=~Z_FLAG;
 41.1021 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1022 +                {
 41.1023 +                        temp2=readmemb(es,DI);
 41.1024 +                        if (abrt) { flags=of; break; }
 41.1025 +                        setsub8(AL,temp2);
 41.1026 +                        if (flags&D_FLAG) DI--;
 41.1027 +                        else              DI++;
 41.1028 +                        c--;
 41.1029 +                        cycles-=(is486)?5:8;
 41.1030 +                }
 41.1031 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1032 +                else firstrepcycle=1;
 41.1033 +                break;
 41.1034 +                case 0x2AE: case 0x3AE: /*REP SCASB*/
 41.1035 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc);
 41.1036 +//                tempz=(fv)?1:0;
 41.1037 +                if (fv) flags|=Z_FLAG;
 41.1038 +                else    flags&=~Z_FLAG;
 41.1039 +//                if (output) pclog("REP SCASB - %i %04X %i\n",fv,flags&Z_FLAG,c);
 41.1040 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1041 +                {
 41.1042 +                        temp2=readmemb(es,EDI);
 41.1043 +                        if (abrt) { flags=of; break; }
 41.1044 +//                        if (output) pclog("Compare %02X,%02X\n",temp2,AL);
 41.1045 +                        setsub8(AL,temp2);
 41.1046 +                        if (flags&D_FLAG) EDI--;
 41.1047 +                        else              EDI++;
 41.1048 +                        c--;
 41.1049 +                        cycles-=(is486)?5:8;
 41.1050 +                }
 41.1051 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1052 +                else firstrepcycle=1;
 41.1053 +                break;
 41.1054 +                case 0xAF: /*REP SCASW*/
 41.1055 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc);
 41.1056 +                if (fv) flags|=Z_FLAG;
 41.1057 +                else    flags&=~Z_FLAG;
 41.1058 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1059 +                {
 41.1060 +                        tempw=readmemw(es,DI);
 41.1061 +                        if (abrt) { flags=of; break; }
 41.1062 +                        setsub16(AX,tempw);
 41.1063 +                        if (flags&D_FLAG) DI-=2;
 41.1064 +                        else              DI+=2;
 41.1065 +                        c--;
 41.1066 +                        cycles-=(is486)?5:8;
 41.1067 +                }
 41.1068 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1069 +                else firstrepcycle=1;
 41.1070 +                break;
 41.1071 +                case 0x1AF: /*REP SCASL*/
 41.1072 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc);
 41.1073 +                if (fv) flags|=Z_FLAG;
 41.1074 +                else    flags&=~Z_FLAG;
 41.1075 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1076 +                {
 41.1077 +                        templ=readmeml(es,DI);
 41.1078 +                        if (abrt) { flags=of; break; }
 41.1079 +                        setsub32(EAX,templ);
 41.1080 +                        if (flags&D_FLAG) DI-=4;
 41.1081 +                        else              DI+=4;
 41.1082 +                        c--;
 41.1083 +                        cycles-=(is486)?5:8;
 41.1084 +                }
 41.1085 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1086 +                else firstrepcycle=1;
 41.1087 +                break;
 41.1088 +                case 0x2AF: /*REP SCASW*/
 41.1089 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc);
 41.1090 +                if (fv) flags|=Z_FLAG;
 41.1091 +                else    flags&=~Z_FLAG;
 41.1092 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1093 +                {
 41.1094 +                        tempw=readmemw(es,EDI);
 41.1095 +                        if (abrt) { flags=of; break; }
 41.1096 +                        setsub16(AX,tempw);
 41.1097 +                        if (flags&D_FLAG) EDI-=2;
 41.1098 +                        else              EDI+=2;
 41.1099 +                        c--;
 41.1100 +                        cycles-=(is486)?5:8;
 41.1101 +                }
 41.1102 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1103 +                else firstrepcycle=1;
 41.1104 +                break;
 41.1105 +                case 0x3AF: /*REP SCASL*/
 41.1106 +//                if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc);
 41.1107 +                if (fv) flags|=Z_FLAG;
 41.1108 +                else    flags&=~Z_FLAG;
 41.1109 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
 41.1110 +                {
 41.1111 +                        templ=readmeml(es,EDI);
 41.1112 +                        if (abrt) { flags=of; break; }
 41.1113 +                        setsub32(EAX,templ);
 41.1114 +                        if (flags&D_FLAG) EDI-=4;
 41.1115 +                        else              EDI+=4;
 41.1116 +                        c--;
 41.1117 +                        cycles-=(is486)?5:8;
 41.1118 +                }
 41.1119 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
 41.1120 +                else firstrepcycle=1;
 41.1121 +                break;
 41.1122 +
 41.1123 +
 41.1124 +                default:
 41.1125 +                        pc=ipc;
 41.1126 +                        cycles-=20;
 41.1127 +                x86illegal();
 41.1128 +                pclog("Bad REP %02X %i\n",temp,rep32>>8);
 41.1129 +        }
 41.1130 +        if (rep32&0x200) ECX=c;
 41.1131 +        else             CX=c;
 41.1132 +        if (changeds) ds=oldds;
 41.1133 +//        if (output) pclog("%03X %03X\n",rep32,use32);
 41.1134 +}
 41.1135 +
 41.1136 +int checkio(int port)
 41.1137 +{
 41.1138 +        uint16_t t;
 41.1139 +        uint8_t d;
 41.1140 +        cpl_override = 1;
 41.1141 +        t = readmemw(tr.base, 0x66);
 41.1142 +        cpl_override = 0;
 41.1143 +//        pclog("CheckIO 1 %08X\n",tr.base);
 41.1144 +        if (abrt) return 0;
 41.1145 +//        pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
 41.1146 +        if ((t+(port>>3))>tr.limit) return 1;
 41.1147 +        cpl_override = 1;
 41.1148 +        d=readmemb(tr.base,t+(port>>3));
 41.1149 +        cpl_override = 0;
 41.1150 +//      pclog("%02X %02X\n",d,d&(1<<(port&7)));
 41.1151 +        return d&(1<<(port&7));
 41.1152 +}
 41.1153 +
 41.1154 +#define getbytef() ((uint8_t)(fetchdat)); pc++
 41.1155 +#define getwordf() ((uint16_t)(fetchdat)); pc+=2
 41.1156 +#define getbyte2f() ((uint8_t)(fetchdat>>8)); pc++
 41.1157 +#define getword2f() ((uint16_t)(fetchdat>>8)); pc+=2
 41.1158 +int xout=0;
 41.1159 +
 41.1160 +
 41.1161 +#define divexcp() { \
 41.1162 +                pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,pc); \
 41.1163 +                pc=oldpc; \
 41.1164 +                if (msw&1) pmodeint(0,0); \
 41.1165 +                else \
 41.1166 +                { \
 41.1167 +                        writememw(ss,(SP-2)&0xFFFF,flags); \
 41.1168 +                        writememw(ss,(SP-4)&0xFFFF,CS); \
 41.1169 +                        writememw(ss,(SP-6)&0xFFFF,pc); \
 41.1170 +                        SP-=6; \
 41.1171 +                        flags&=~I_FLAG; \
 41.1172 +                        oxpc=pc; \
 41.1173 +                        pc=readmemw(0,0); \
 41.1174 +                        loadcs(readmemw(0,2)); \
 41.1175 +                } \
 41.1176 +                return; \
 41.1177 +}
 41.1178 +
 41.1179 +void divl(uint32_t val)
 41.1180 +{
 41.1181 +        if (val==0) divexcp();
 41.1182 +        uint64_t num=(((uint64_t)EDX)<<32)|EAX;
 41.1183 +        uint64_t quo=num/val;
 41.1184 +        uint32_t rem=num%val;
 41.1185 +        uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
 41.1186 +        if (quo!=(uint64_t)quo32) divexcp();
 41.1187 +        EDX=rem;
 41.1188 +        EAX=quo32;
 41.1189 +}
 41.1190 +void idivl(int32_t val)
 41.1191 +{
 41.1192 +        if (val==0) divexcp();
 41.1193 +        int64_t num=(((uint64_t)EDX)<<32)|EAX;
 41.1194 +        int64_t quo=num/val;
 41.1195 +        int32_t rem=num%val;
 41.1196 +        int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
 41.1197 +        if (quo!=(int64_t)quo32) divexcp();
 41.1198 +        EDX=rem;
 41.1199 +        EAX=quo32;
 41.1200 +}
 41.1201 +
 41.1202 +int oldi;
 41.1203 +
 41.1204 +uint32_t testr[9];
 41.1205 +int dontprint=0;
 41.1206 +void exec386(int cycs)
 41.1207 +{
 41.1208 +        uint64_t temp64;
 41.1209 +        int64_t temp64i;
 41.1210 +        uint8_t temp,temp2;
 41.1211 +        uint16_t tempw,tempw2,tempw3,tempw4;
 41.1212 +        int8_t offset;
 41.1213 +        int8_t temps;
 41.1214 +        int16_t temps16;
 41.1215 +        volatile int tempws,tempws2;
 41.1216 +        uint32_t templ,templ2,templ3,addr;
 41.1217 +        int c,cycdiff;
 41.1218 +        int oldcyc;
 41.1219 +        int tempi;
 41.1220 +        int cyctot=0;
 41.1221 +        int trap;
 41.1222 +
 41.1223 +        FILE *f;
 41.1224 +        
 41.1225 +        cycles+=cycs;
 41.1226 +//        output=3;
 41.1227 +        while (cycles>0)
 41.1228 +        {
 41.1229 +                cycdiff=0;
 41.1230 +                oldcyc=cycles;
 41.1231 +//                pclog("%i %02X\n", ins, ram[8]);
 41.1232 +                while (cycdiff<100)
 41.1233 +                {
 41.1234 +/*                        testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
 41.1235 +                        testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;
 41.1236 +                        testr[8]=flags;*/
 41.1237 +//                oldcs2=oldcs;
 41.1238 +//                oldpc2=oldpc;
 41.1239 +                oldcs=CS;
 41.1240 +                oldpc=pc;
 41.1241 +                oldcpl=CPL;
 41.1242 +                op32=use32;
 41.1243 +                
 41.1244 +dontprint=0;
 41.1245 +
 41.1246 +                opcodestart:
 41.1247 +                fetchdat=fastreadl(cs+pc);
 41.1248 +                if (abrt) goto opcodeend;
 41.1249 +                
 41.1250 +                tempc=flags&C_FLAG;
 41.1251 +                trap=flags&T_FLAG;
 41.1252 +                opcode=fetchdat&0xFF;
 41.1253 +                fetchdat>>=8;
 41.1254 +
 41.1255 +                if (output==3 && !dontprint)
 41.1256 +                {
 41.1257 +                        if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
 41.1258 +                        {
 41.1259 +                                if (!skipnextprint)
 41.1260 +                                {
 41.1261 +                                        pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X  %08X %i %i %02X %02X %02X   %02X %02X %02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,writelookup2, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, readmode);
 41.1262 +                                        //x87_print();
 41.1263 +                                }
 41.1264 +                                skipnextprint=0;
 41.1265 +                        }
 41.1266 +                }
 41.1267 +                dontprint=1;
 41.1268 +//#endif
 41.1269 +                pc++;
 41.1270 +                inhlt=0;
 41.1271 +                switch ((opcode|op32)&0x3FF)
 41.1272 +                {
 41.1273 +                        case 0x00: case 0x100: case 0x200: case 0x300: /*ADD 8,reg*/
 41.1274 +                        fetchea();
 41.1275 +                        //if (!rmdat && output) pc--;
 41.1276 +/*                        if (!rmdat && output)
 41.1277 +                        {
 41.1278 +                                fatal("Crashed\n");
 41.1279 +//                                clear_keybuf();
 41.1280 +//                                readkey();
 41.1281 +
 41.1282 +
 41.1283 +                        }*/
 41.1284 +                        if (mod == 3)
 41.1285 +                        {
 41.1286 +                                temp  = getr8(rm);
 41.1287 +                                temp2 = getr8(reg);
 41.1288 +                                setadd8(temp, temp2);
 41.1289 +                                setr8(rm, temp + temp2);
 41.1290 +                                cycles -= timing_rr;
 41.1291 +                        }
 41.1292 +                        else
 41.1293 +                        {
 41.1294 +                                temp  = geteab();     if (abrt) break;
 41.1295 +                                temp2 = getr8(reg);
 41.1296 +                                seteab(temp + temp2); if (abrt) break;
 41.1297 +                                setadd8(temp, temp2);
 41.1298 +                                cycles -= timing_mr;
 41.1299 +                        }
 41.1300 +                        break;
 41.1301 +                        case 0x01: case 0x201: /*ADD 16,reg*/
 41.1302 +                        fetchea();
 41.1303 +                        if (mod == 3)
 41.1304 +                        {
 41.1305 +                                setadd16(regs[rm].w, regs[reg].w);
 41.1306 +                                regs[rm].w += regs[reg].w;
 41.1307 +                                cycles -= timing_rr;
 41.1308 +                        }
 41.1309 +                        else
 41.1310 +                        {
 41.1311 +                                tempw = geteaw();             if (abrt) break;
 41.1312 +                                seteaw(tempw + regs[reg].w);  if (abrt) break;
 41.1313 +                                setadd16(tempw, regs[reg].w);
 41.1314 +                                cycles -= timing_mr;
 41.1315 +                        }
 41.1316 +                        break;
 41.1317 +                        case 0x101: case 0x301: /*ADD 32,reg*/
 41.1318 +                        fetchea();
 41.1319 +                        if (mod == 3)
 41.1320 +                        {
 41.1321 +                                setadd32(regs[rm].l, regs[reg].l);
 41.1322 +                                regs[rm].l += regs[reg].l;
 41.1323 +                                cycles -= timing_rr;
 41.1324 +                        }
 41.1325 +                        else
 41.1326 +                        {
 41.1327 +                                templ = geteal();             if (abrt) break;
 41.1328 +                                seteal(templ + regs[reg].l);  if (abrt) break;
 41.1329 +                                setadd32(templ, regs[reg].l);
 41.1330 +                                cycles -= timing_mrl;
 41.1331 +                        }
 41.1332 +                        break;
 41.1333 +                        case 0x02: case 0x102: case 0x202: case 0x302: /*ADD reg,8*/
 41.1334 +                        fetchea();
 41.1335 +                        temp=geteab();        if (abrt) break;
 41.1336 +                        setadd8(getr8(reg),temp);
 41.1337 +                        setr8(reg,getr8(reg)+temp);
 41.1338 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.1339 +                        break;
 41.1340 +                        case 0x03: case 0x203: /*ADD reg,16*/
 41.1341 +                        fetchea();
 41.1342 +                        tempw=geteaw();       if (abrt) break;
 41.1343 +                        setadd16(regs[reg].w,tempw);
 41.1344 +                        regs[reg].w+=tempw;
 41.1345 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.1346 +                        break;
 41.1347 +                        case 0x103: case 0x303: /*ADD reg,32*/
 41.1348 +                        fetchea();
 41.1349 +                        templ=geteal();       if (abrt) break;
 41.1350 +                        setadd32(regs[reg].l,templ);
 41.1351 +                        regs[reg].l+=templ;
 41.1352 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.1353 +                        break;
 41.1354 +                        case 0x04: case 0x104: case 0x204: case 0x304: /*ADD AL,#8*/
 41.1355 +                        temp=getbytef();
 41.1356 +                        setadd8(AL,temp);
 41.1357 +                        AL+=temp;
 41.1358 +                        cycles -= timing_rr;
 41.1359 +                        break;
 41.1360 +                        case 0x05: case 0x205: /*ADD AX,#16*/
 41.1361 +                        tempw=getwordf();
 41.1362 +                        setadd16(AX,tempw);
 41.1363 +                        AX+=tempw;
 41.1364 +                        cycles -= timing_rr;
 41.1365 +                        break;
 41.1366 +                        case 0x105: case 0x305: /*ADD EAX,#32*/
 41.1367 +                        templ=getlong(); if (abrt) break;
 41.1368 +                        setadd32(EAX,templ);
 41.1369 +                        EAX+=templ;
 41.1370 +                        cycles -= timing_rr;
 41.1371 +                        break;
 41.1372 +
 41.1373 +                        case 0x06: case 0x206: /*PUSH ES*/
 41.1374 +                        if (ssegs) ss=oldss;
 41.1375 +                        if (stack32)
 41.1376 +                        {
 41.1377 +                                writememw(ss,ESP-2,ES);           if (abrt) break;
 41.1378 +                                ESP-=2;
 41.1379 +                        }
 41.1380 +                        else
 41.1381 +                        {
 41.1382 +                                writememw(ss,((SP-2)&0xFFFF),ES); if (abrt) break;
 41.1383 +                                SP-=2;
 41.1384 +                        }
 41.1385 +                        cycles-=2;
 41.1386 +                        break;
 41.1387 +                        case 0x106: case 0x306: /*PUSH ES*/
 41.1388 +                        if (ssegs) ss=oldss;
 41.1389 +                        if (stack32)
 41.1390 +                        {
 41.1391 +                                writememl(ss,ESP-4,ES);           if (abrt) break;
 41.1392 +                                ESP-=4;
 41.1393 +                        }
 41.1394 +                        else
 41.1395 +                        {
 41.1396 +                                writememl(ss,((SP-4)&0xFFFF),ES); if (abrt) break;
 41.1397 +                                SP-=4;
 41.1398 +                        }
 41.1399 +                        cycles-=2;
 41.1400 +                        break;
 41.1401 +                        case 0x07: case 0x207: /*POP ES*/
 41.1402 +                        if (ssegs) ss=oldss;
 41.1403 +                        if (stack32)
 41.1404 +                        {
 41.1405 +                                tempw=readmemw(ss,ESP);         if (abrt) break;
 41.1406 +                                loadseg(tempw,&_es);            if (abrt) break;
 41.1407 +                                ESP+=2;
 41.1408 +                        }
 41.1409 +                        else
 41.1410 +                        {
 41.1411 +                                tempw=readmemw(ss,SP);          if (abrt) break;
 41.1412 +                                loadseg(tempw,&_es);            if (abrt) break;
 41.1413 +                                SP+=2;
 41.1414 +                        }
 41.1415 +                        cycles-=(is486)?3:7;
 41.1416 +                        break;
 41.1417 +                        case 0x107: case 0x307: /*POP ES*/
 41.1418 +                        if (ssegs) ss=oldss;
 41.1419 +                        if (stack32)
 41.1420 +                        {
 41.1421 +                                tempw=readmeml(ss,ESP)&0xFFFF;  if (abrt) break;
 41.1422 +                                loadseg(tempw,&_es);            if (abrt) break;
 41.1423 +                                ESP+=4;
 41.1424 +                        }
 41.1425 +                        else
 41.1426 +                        {
 41.1427 +                                tempw=readmemw(ss,SP);          if (abrt) break;
 41.1428 +                                loadseg(tempw,&_es);            if (abrt) break;
 41.1429 +                                SP+=4;
 41.1430 +                        }
 41.1431 +                        cycles-=(is486)?3:7;
 41.1432 +                        break;
 41.1433 +
 41.1434 +
 41.1435 +                        case 0x08: case 0x108: case 0x208: case 0x308: /*OR 8,reg*/
 41.1436 +                        fetchea();
 41.1437 +                        if (mod == 3)
 41.1438 +                        {
 41.1439 +                                temp  = getr8(rm) | getr8(reg);
 41.1440 +                                setr8(rm, temp);
 41.1441 +                                setznp8(temp);
 41.1442 +                                cycles -= timing_rr;
 41.1443 +                        }
 41.1444 +                        else
 41.1445 +                        {
 41.1446 +                                temp  = geteab();          if (abrt) break;
 41.1447 +                                temp2 = getr8(reg);
 41.1448 +                                seteab(temp | temp2);     if (abrt) break;
 41.1449 +                                setznp8(temp | temp2);
 41.1450 +                                cycles -= timing_mr;
 41.1451 +                        }
 41.1452 +                        break;
 41.1453 +                        case 0x09: case 0x209: /*OR 16,reg*/
 41.1454 +                        fetchea();
 41.1455 +                        if (mod == 3)
 41.1456 +                        {
 41.1457 +                                regs[rm].w |= regs[reg].w;
 41.1458 +                                setznp16(regs[rm].w);
 41.1459 +                                cycles -= timing_rr;
 41.1460 +                        }
 41.1461 +                        else
 41.1462 +                        {
 41.1463 +                                tempw = geteaw() | regs[reg].w; if (abrt) break;
 41.1464 +                                seteaw(tempw);                  if (abrt) break;
 41.1465 +                                setznp16(tempw);
 41.1466 +                                cycles -= timing_mr;
 41.1467 +                        }
 41.1468 +                        break;
 41.1469 +                        case 0x109: case 0x309: /*OR 32,reg*/
 41.1470 +                        fetchea();
 41.1471 +                        if (mod == 3)
 41.1472 +                        {
 41.1473 +                                regs[rm].l |= regs[reg].l;
 41.1474 +                                setznp32(regs[rm].l);
 41.1475 +                                cycles -= timing_rr;
 41.1476 +                        }
 41.1477 +                        else
 41.1478 +                        {
 41.1479 +                                templ = geteal() | regs[reg].l; if (abrt) break;
 41.1480 +                                seteal(templ);                  if (abrt) break;
 41.1481 +                                setznp32(templ);
 41.1482 +                                cycles -= timing_mrl;
 41.1483 +                        }
 41.1484 +                        break;
 41.1485 +                        case 0x0A: case 0x10A: case 0x20A: case 0x30A: /*OR reg,8*/
 41.1486 +                        fetchea();
 41.1487 +                        temp=geteab();          if (abrt) break;
 41.1488 +                        temp|=getr8(reg);
 41.1489 +                        setznp8(temp);
 41.1490 +                        setr8(reg,temp);
 41.1491 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.1492 +                        break;
 41.1493 +                        case 0x0B: case 0x20B: /*OR reg,16*/
 41.1494 +                        fetchea();
 41.1495 +                        tempw=geteaw();         if (abrt) break;
 41.1496 +                        tempw|=regs[reg].w;
 41.1497 +                        setznp16(tempw);
 41.1498 +                        regs[reg].w=tempw;
 41.1499 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.1500 +                        break;
 41.1501 +                        case 0x10B: case 0x30B: /*OR reg,32*/
 41.1502 +                        fetchea();
 41.1503 +                        templ=geteal();         if (abrt) break;
 41.1504 +                        templ|=regs[reg].l;
 41.1505 +                        setznp32(templ);
 41.1506 +                        regs[reg].l=templ;
 41.1507 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.1508 +                        break;
 41.1509 +                        case 0x0C: case 0x10C: case 0x20C: case 0x30C: /*OR AL,#8*/
 41.1510 +                        AL|=getbytef();
 41.1511 +                        setznp8(AL);
 41.1512 +                        cycles -= timing_rr;
 41.1513 +                        break;
 41.1514 +                        case 0x0D: case 0x20D: /*OR AX,#16*/
 41.1515 +                        AX|=getwordf();
 41.1516 +                        setznp16(AX);
 41.1517 +                        cycles -= timing_rr;
 41.1518 +                        break;
 41.1519 +                        case 0x10D: case 0x30D: /*OR AX,#32*/
 41.1520 +                        templ=getlong(); if (abrt) break;
 41.1521 +                        EAX|=templ;
 41.1522 +                        setznp32(EAX);
 41.1523 +                        cycles -= timing_rr;
 41.1524 +                        break;
 41.1525 +
 41.1526 +                        case 0x0E: case 0x20E: /*PUSH CS*/
 41.1527 +                        if (ssegs) ss=oldss;
 41.1528 +                        if (stack32)
 41.1529 +                        {
 41.1530 +                                writememw(ss,ESP-2,CS);                 if (abrt) break;
 41.1531 +                                ESP-=2;
 41.1532 +                        }
 41.1533 +                        else
 41.1534 +                        {
 41.1535 +                                writememw(ss,((SP-2)&0xFFFF),CS);       if (abrt) break;
 41.1536 +                                SP-=2;
 41.1537 +                        }
 41.1538 +                        cycles-=2;
 41.1539 +                        break;
 41.1540 +                        case 0x10E: case 0x30E: /*PUSH CS*/
 41.1541 +                        if (ssegs) ss=oldss;
 41.1542 +                        if (stack32)
 41.1543 +                        {
 41.1544 +                                writememl(ss,ESP-4,CS);                 if (abrt) break;
 41.1545 +                                ESP-=4;
 41.1546 +                        }
 41.1547 +                        else
 41.1548 +                        {
 41.1549 +                                writememl(ss,((SP-4)&0xFFFF),CS);       if (abrt) break;
 41.1550 +                                SP-=4;
 41.1551 +                        }
 41.1552 +                        cycles-=2;
 41.1553 +                        break;
 41.1554 +
 41.1555 +                        case 0x0F: case 0x20F:
 41.1556 +                        temp=fetchdat&0xFF/*readmemb(cs+pc)*/; pc++;
 41.1557 +                        opcode2=temp;
 41.1558 +//                        if (temp>5 && temp!=0x82 && temp!=0x85 && temp!=0x84 && temp!=0x87 && temp!=0x8D && temp!=0x8F && temp!=0x8C && temp!=0x20 && temp!=0x22) pclog("Using magic 386 0F instruction %02X!\n",temp);
 41.1559 +                        switch (temp)
 41.1560 +                        {
 41.1561 +                                case 0:
 41.1562 +                                if (!(cr0&1) || (eflags&VM_FLAG)) goto inv16;
 41.1563 +                                fetchea2(); if (abrt) break;
 41.1564 +                                switch (rmdat&0x38)
 41.1565 +                                {
 41.1566 +                                        case 0x00: /*SLDT*/
 41.1567 +                                        NOTRM
 41.1568 +                                        seteaw(ldt.seg);
 41.1569 +                                        cycles-=4;
 41.1570 +                                        break;
 41.1571 +                                        case 0x08: /*STR*/
 41.1572 +                                        NOTRM
 41.1573 +                                        seteaw(tr.seg);
 41.1574 +                                        cycles-=4;
 41.1575 +                                        break;
 41.1576 +                                        case 0x10: /*LLDT*/
 41.1577 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.1578 +                                        {
 41.1579 +                                                pclog("Invalid LLDT!\n");
 41.1580 +                                                x86gpf(NULL,0);
 41.1581 +                                                break;
 41.1582 +                                        }
 41.1583 +                                        NOTRM
 41.1584 +                                        ldt.seg=geteaw();
 41.1585 +//                                        pclog("Load LDT %04X ",ldt.seg);
 41.1586 +                                        templ=(ldt.seg&~7)+gdt.base;
 41.1587 +//                                        pclog("%06X ",gdt.base);
 41.1588 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
 41.1589 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
 41.1590 +                                        if (abrt) break;
 41.1591 +                                        ldt.limit=templ3;
 41.1592 +                                        ldt.access=readmemb(0,templ+6);
 41.1593 +                                        if (readmemb(0,templ+6)&0x80)
 41.1594 +                                        {
 41.1595 +                                                ldt.limit<<=12;
 41.1596 +                                                ldt.limit|=0xFFF;
 41.1597 +                                        }
 41.1598 +                                        ldt.base=templ2;
 41.1599 +//                                        /*if (output==3) */pclog("LLDT %04X %08X %04X  %08X %08X\n",ldt.seg,ldt.base,ldt.limit,readmeml(0,templ),readmeml(0,templ+4));
 41.1600 +
 41.1601 +                                        cycles-=20;
 41.1602 +                                        break;
 41.1603 +                                        case 0x18: /*LTR*/
 41.1604 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.1605 +                                        {
 41.1606 +                                                pclog("Invalid LTR!\n");
 41.1607 +                                                x86gpf(NULL,0);
 41.1608 +                                                break;
 41.1609 +                                        }
 41.1610 +                                        NOTRM
 41.1611 +                                        tr.seg=geteaw();
 41.1612 +                                        templ=(tr.seg&~7)+gdt.base;
 41.1613 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
 41.1614 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
 41.1615 +                                        temp=readmemb(0,templ+5);
 41.1616 +                                        if (abrt) break;
 41.1617 +                                        tr.limit=templ3;
 41.1618 +                                        tr.access=readmemb(0,templ+6);
 41.1619 +                                        if (readmemb(0,templ+6)&0x80)
 41.1620 +                                        {
 41.1621 +                                                tr.limit<<=12;
 41.1622 +                                                tr.limit|=0xFFF;
 41.1623 +                                        }
 41.1624 +                                        tr.base=templ2;
 41.1625 +//                                        pclog("TR base = %08X\n",templ2);
 41.1626 +                                        tr.access=temp;
 41.1627 +                                        cycles-=20;
 41.1628 +                                        break;
 41.1629 +                                        case 0x20: /*VERR*/
 41.1630 +                                        NOTRM
 41.1631 +                                        tempw=geteaw(); if (abrt) break;
 41.1632 +                                        flags&=~Z_FLAG;
 41.1633 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
 41.1634 +                                        cpl_override=1;
 41.1635 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.1636 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.1637 +                                        cpl_override=0;
 41.1638 +                                        if (abrt) break;
 41.1639 +                                        if (!(tempw2&0x1000)) tempi=0;
 41.1640 +                                        if ((tempw2&0xC00)!=0xC00) /*Exclude conforming code segments*/
 41.1641 +                                        {
 41.1642 +                                                tempw3=(tempw2>>13)&3; /*Check permissions*/
 41.1643 +                                                if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.1644 +                                        }
 41.1645 +                                        if ((tempw2&0x0800) && !(tempw2&0x0200)) tempi=0; /*Non-readable code*/
 41.1646 +                                        if (tempi) flags|=Z_FLAG;
 41.1647 +                                        cycles-=20;
 41.1648 +                                        break;
 41.1649 +                                        case 0x28: /*VERW*/
 41.1650 +                                        NOTRM
 41.1651 +                                        tempw=geteaw(); if (abrt) break;
 41.1652 +                                        flags&=~Z_FLAG;
 41.1653 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
 41.1654 +                                        cpl_override=1;
 41.1655 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.1656 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.1657 +                                        cpl_override=0;
 41.1658 +                                        if (abrt) break;
 41.1659 +                                        if (!(tempw2&0x1000)) tempi=0;
 41.1660 +                                        tempw3=(tempw2>>13)&3; /*Check permissions*/
 41.1661 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.1662 +                                        if (tempw2&0x0800) tempi=0; /*Code*/
 41.1663 +                                        else if (!(tempw2&0x0200)) tempi=0; /*Read-only data*/
 41.1664 +                                        if (tempi) flags|=Z_FLAG;
 41.1665 +                                        cycles-=20;
 41.1666 +                                        break;
 41.1667 +
 41.1668 +
 41.1669 +                                        default:
 41.1670 +                                        pclog("Bad 0F 00 opcode %02X\n",rmdat&0x38);
 41.1671 +                                        pc-=3;
 41.1672 +                                        x86illegal();
 41.1673 +                                        break;
 41.1674 +                                }
 41.1675 +                                break;
 41.1676 +                                case 1:
 41.1677 +                                fetchea2(); if (abrt) break;
 41.1678 +                                switch (rmdat&0x38)
 41.1679 +                                {
 41.1680 +                                        case 0x00: /*SGDT*/
 41.1681 +                                        seteaw(gdt.limit);
 41.1682 +                                        writememw(easeg,eaaddr+2,gdt.base);
 41.1683 +                                        writememw(easeg,eaaddr+4,(gdt.base>>16)&0xFF);
 41.1684 +                                        cycles-=7; //less seteaw time
 41.1685 +                                        break;
 41.1686 +                                        case 0x08: /*SIDT*/
 41.1687 +                                        seteaw(idt.limit);
 41.1688 +                                        writememw(easeg,eaaddr+2,idt.base);
 41.1689 +                                        writememw(easeg,eaaddr+4,(idt.base>>16)&0xFF);
 41.1690 +                                        cycles-=7;
 41.1691 +                                        break;
 41.1692 +                                        case 0x10: /*LGDT*/
 41.1693 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.1694 +                                        {
 41.1695 +                                                pclog("Invalid LGDT!\n");
 41.1696 +                                                x86gpf(NULL,0);
 41.1697 +                                                break;
 41.1698 +                                        }
 41.1699 +                                        tempw=geteaw();
 41.1700 +                                        templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF;
 41.1701 +                                        if (abrt) break;
 41.1702 +                                        gdt.limit=tempw;
 41.1703 +                                        gdt.base=templ;
 41.1704 +                                        cycles-=11;
 41.1705 +                                        break;
 41.1706 +                                        case 0x18: /*LIDT*/
 41.1707 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.1708 +                                        {
 41.1709 +                                                pclog("Invalid LIDT!\n");
 41.1710 +                                                x86gpf(NULL,0);
 41.1711 +                                                break;
 41.1712 +                                        }
 41.1713 +                                        tempw=geteaw();
 41.1714 +                                        templ=readmeml(0,easeg+eaaddr+2)&0xFFFFFF;
 41.1715 +                                        if (abrt) break;
 41.1716 +                                        idt.limit=tempw;
 41.1717 +                                        idt.base=templ;
 41.1718 +                                        cycles-=11;
 41.1719 +                                        break;
 41.1720 +
 41.1721 +                                        case 0x20: /*SMSW*/
 41.1722 +                                        if (is486) seteaw(msw);
 41.1723 +                                        else       seteaw(msw|0xFF00);
 41.1724 +//                                        pclog("SMSW %04X:%04X  %04X %i\n",CS,pc,msw,is486);
 41.1725 +                                        cycles-=2;
 41.1726 +                                        break;
 41.1727 +                                        case 0x30: /*LMSW*/
 41.1728 +                                        if ((CPL || eflags&VM_FLAG) && (msw&1))
 41.1729 +                                        {
 41.1730 +                                                pclog("LMSW - ring not zero!\n");
 41.1731 +                                                x86gpf(NULL,0);
 41.1732 +                                                break;
 41.1733 +                                        }
 41.1734 +                                        tempw=geteaw(); if (abrt) break;
 41.1735 +                                        if (msw&1) tempw|=1;
 41.1736 +                                        msw=tempw;
 41.1737 +                                        break;
 41.1738 +
 41.1739 +                                        default:
 41.1740 +                                        pclog("Bad 0F 01 opcode %02X\n",rmdat&0x38);
 41.1741 +                                        pc-=3;
 41.1742 +                                        x86illegal();
 41.1743 +                                        break;
 41.1744 +                                }
 41.1745 +                                break;
 41.1746 +
 41.1747 +                                case 2: /*LAR*/
 41.1748 +                                NOTRM
 41.1749 +                                fetchea2();
 41.1750 +                                tempw=geteaw(); if (abrt) break;
 41.1751 +//                                pclog("LAR seg %04X\n",tempw);
 41.1752 +                                
 41.1753 +                                if (!(tempw&0xFFFC)) { flags&=~Z_FLAG; break; } /*Null selector*/
 41.1754 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.1755 +                                if (tempi)
 41.1756 +                                {
 41.1757 +                                        cpl_override=1;
 41.1758 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.1759 +                                        cpl_override=0;
 41.1760 +                                        if (abrt) break;
 41.1761 +                                }
 41.1762 +                                flags&=~Z_FLAG;
 41.1763 +//                                pclog("tempw2 %04X  %i  %04X %04X\n",tempw2,tempi,ldt.limit,gdt.limit);
 41.1764 +                                if ((tempw2&0x1F00)==0x000) tempi=0;
 41.1765 +                                if ((tempw2&0x1F00)==0x800) tempi=0;
 41.1766 +                                if ((tempw2&0x1F00)==0xA00) tempi=0;
 41.1767 +                                if ((tempw2&0x1F00)==0xD00) tempi=0;
 41.1768 +                                if ((tempw2&0x1C00)<0x1C00) /*Exclude conforming code segments*/
 41.1769 +                                {
 41.1770 +                                        tempw3=(tempw2>>13)&3;
 41.1771 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.1772 +                                }
 41.1773 +                                if (tempi)
 41.1774 +                                {
 41.1775 +                                        flags|=Z_FLAG;
 41.1776 +                                        cpl_override=1;
 41.1777 +                                        regs[reg].w=readmemb(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+5)<<8;
 41.1778 +                                        cpl_override=0;
 41.1779 +                                }
 41.1780 +                                cycles-=11;
 41.1781 +                                break;
 41.1782 +
 41.1783 +                                case 3: /*LSL*/
 41.1784 +                                NOTRM
 41.1785 +                                fetchea2();
 41.1786 +                                tempw=geteaw(); if (abrt) break;
 41.1787 +                                flags&=~Z_FLAG;
 41.1788 +                                if (!(tempw&0xFFFC)) break; /*Null selector*/
 41.1789 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.1790 +                                cpl_override=1;
 41.1791 +                                if (tempi)
 41.1792 +                                {
 41.1793 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.1794 +                                }
 41.1795 +                                cpl_override=0;
 41.1796 +                                if (abrt) break;
 41.1797 +                                if ((tempw2&0x1400)==0x400) tempi=0; /*Interrupt or trap or call gate*/
 41.1798 +                                if ((tempw2&0x1F00)==0x000) tempi=0; /*Invalid*/
 41.1799 +                                if ((tempw2&0x1F00)==0xA00) tempi=0; /*Invalid*/
 41.1800 +                                if ((tempw2&0x1C00)!=0x1C00) /*Exclude conforming code segments*/
 41.1801 +                                {
 41.1802 +                                        tempw3=(tempw2>>13)&3;
 41.1803 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.1804 +                                }
 41.1805 +                                if (tempi)
 41.1806 +                                {
 41.1807 +                                        flags|=Z_FLAG;
 41.1808 +                                        cpl_override=1;
 41.1809 +                                        regs[reg].w=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7));
 41.1810 +                                        cpl_override=0;
 41.1811 +                                }
 41.1812 +                                cycles-=10;
 41.1813 +                                break;
 41.1814 +
 41.1815 +                                case 5: /*LOADALL*/
 41.1816 +//                                pclog("At %04X:%04X  ",CS,pc);
 41.1817 +                                flags=(readmemw(0,0x818)&0xFFD5)|2;
 41.1818 +                                pc=readmemw(0,0x81A);
 41.1819 +                                DS=readmemw(0,0x81E);
 41.1820 +                                SS=readmemw(0,0x820);
 41.1821 +                                CS=readmemw(0,0x822);
 41.1822 +                                ES=readmemw(0,0x824);
 41.1823 +                                DI=readmemw(0,0x826);
 41.1824 +                                SI=readmemw(0,0x828);
 41.1825 +                                BP=readmemw(0,0x82A);
 41.1826 +                                SP=readmemw(0,0x82C);
 41.1827 +                                BX=readmemw(0,0x82E);
 41.1828 +                                DX=readmemw(0,0x830);
 41.1829 +                                CX=readmemw(0,0x832);
 41.1830 +                                AX=readmemw(0,0x834);
 41.1831 +                                es=readmemw(0,0x836)|(readmemb(0,0x838)<<16);
 41.1832 +                                cs=readmemw(0,0x83C)|(readmemb(0,0x83E)<<16);
 41.1833 +                                ss=readmemw(0,0x842)|(readmemb(0,0x844)<<16);
 41.1834 +                                ds=readmemw(0,0x848)|(readmemb(0,0x84A)<<16);
 41.1835 +                                cycles-=195;
 41.1836 +//                                pclog("LOADALL - %06X:%04X %06X:%04X %04X\n",ds,SI,es,DI,DX);
 41.1837 +                                break;
 41.1838 +                                
 41.1839 +                                case 6: /*CLTS*/
 41.1840 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1841 +                                {
 41.1842 +                                        pclog("Can't CLTS\n");
 41.1843 +                                        x86gpf(NULL,0);
 41.1844 +                                        break;
 41.1845 +                                }
 41.1846 +                                cr0&=~8;
 41.1847 +                                cycles-=5;
 41.1848 +                                break;
 41.1849 +                                
 41.1850 +                                case 8: /*INVD*/
 41.1851 +                                if (!is486) goto inv16;
 41.1852 +                                cycles-=1000;
 41.1853 +                                break;
 41.1854 +                                case 9: /*WBINVD*/
 41.1855 +                                if (!is486) goto inv16;
 41.1856 +                                cycles-=10000;
 41.1857 +                                break;
 41.1858 +
 41.1859 +                                case 0x20: /*MOV reg32,CRx*/
 41.1860 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1861 +                                {
 41.1862 +                                        pclog("Can't load from CRx\n");
 41.1863 +                                        x86gpf(NULL,0);
 41.1864 +                                        break;
 41.1865 +                                }
 41.1866 +                                fetchea2();
 41.1867 +                                switch (reg)
 41.1868 +                                {
 41.1869 +                                        case 0:
 41.1870 +                                        regs[rm].l=cr0;//&~2;
 41.1871 +                                        if (is486) regs[rm].l|=0x10; /*ET hardwired on 486*/
 41.1872 +                                        break;
 41.1873 +                                        case 2:
 41.1874 +                                        regs[rm].l=cr2;
 41.1875 +                                        break;
 41.1876 +                                        case 3:
 41.1877 +                                        regs[rm].l=cr3;
 41.1878 +                                        break;
 41.1879 +                                        default:
 41.1880 +                                        pclog("Bad read of CR%i %i\n",rmdat&7,reg);
 41.1881 +                                        pc=oldpc;
 41.1882 +                                        x86illegal();
 41.1883 +                                        break;
 41.1884 +                                }
 41.1885 +                                cycles-=6;
 41.1886 +                                break;
 41.1887 +                                case 0x21: /*MOV reg32,DRx*/
 41.1888 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1889 +                                {
 41.1890 +                                        pclog("Can't load from DRx\n");
 41.1891 +                                        x86gpf(NULL,0);
 41.1892 +                                        break;
 41.1893 +                                }
 41.1894 +                                fetchea2();
 41.1895 +                                regs[rm].l=0;
 41.1896 +                                cycles-=6;
 41.1897 +                                break;
 41.1898 +                                case 0x22: /*MOV CRx,reg32*/
 41.1899 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1900 +                                {
 41.1901 +                                        pclog("Can't load CRx\n");
 41.1902 +                                        x86gpf(NULL,0);
 41.1903 +                                        break;
 41.1904 +                                }
 41.1905 +                                fetchea2();
 41.1906 +                                switch (reg)
 41.1907 +                                {
 41.1908 +                                        case 0:
 41.1909 +                                        //if ((cr0^regs[rm].l)>>31) flushmmucache();
 41.1910 +                                        if ((regs[rm].l^cr0) & 0x80000001) flushmmucache();
 41.1911 +                                        cr0=regs[rm].l;//&~2;
 41.1912 +                                        if (cpu_16bitbus) cr0 |= 0x10;
 41.1913 +//                                        if (cs<0xF0000 && cr0&1) output=3;
 41.1914 +                                        if (cr0&0x80000000)
 41.1915 +                                        {
 41.1916 +                                        }
 41.1917 +                                        else mmu_perm=4;
 41.1918 +                                        break;
 41.1919 +                                        case 2:
 41.1920 +                                        cr2=regs[rm].l;
 41.1921 +                                        break;
 41.1922 +                                        case 3:
 41.1923 +                                        cr3=regs[rm].l&~0xFFF;
 41.1924 +//                                        pclog("Loading CR3 with %08X at %08X:%08X\n",cr3,cs,pc);
 41.1925 +//                                        if (pc==0x204) output=3;
 41.1926 +                                        flushmmucache();
 41.1927 +                                        break;
 41.1928 +                                        default:
 41.1929 +                                        pclog("Bad load CR%i\n",reg);
 41.1930 +                                        pc=oldpc;
 41.1931 +                                        x86illegal();
 41.1932 +                                        break;
 41.1933 +                                }
 41.1934 +                                cycles-=10;
 41.1935 +                                break;
 41.1936 +                                case 0x23: /*MOV DRx,reg32*/
 41.1937 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1938 +                                {
 41.1939 +                                        pclog("Can't load DRx\n");
 41.1940 +                                        x86gpf(NULL,0);
 41.1941 +                                        break;
 41.1942 +                                }
 41.1943 +                                fetchea2();
 41.1944 +                                cycles-=6;
 41.1945 +                                break;
 41.1946 +                                case 0x24: /*MOV reg32,TRx*/
 41.1947 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1948 +                                {
 41.1949 +                                        pclog("Can't load from TRx\n");
 41.1950 +                                        x86gpf(NULL,0);
 41.1951 +                                        break;
 41.1952 +                                }
 41.1953 +                                fetchea2();
 41.1954 +                                regs[rm].l=0;
 41.1955 +                                cycles-=6;
 41.1956 +                                break;
 41.1957 +                                case 0x26: /*MOV TRx,reg32*/
 41.1958 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.1959 +                                {
 41.1960 +                                        pclog("Can't load TRx\n");
 41.1961 +                                        x86gpf(NULL,0);
 41.1962 +                                        break;
 41.1963 +                                }
 41.1964 +                                fetchea2();
 41.1965 +                                cycles-=6;
 41.1966 +                                break;
 41.1967 +
 41.1968 +                                case 0x32: x86illegal(); break;
 41.1969 +                                
 41.1970 +                                case 0x80: /*JO*/
 41.1971 +                                tempw=getword2f();
 41.1972 +                                if (flags&V_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1973 +                                cycles -= timing_bnt;
 41.1974 +                                break;
 41.1975 +                                case 0x81: /*JNO*/
 41.1976 +                                tempw=getword2f();
 41.1977 +                                if (!(flags&V_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1978 +                                cycles -= timing_bnt;
 41.1979 +                                break;
 41.1980 +                                case 0x82: /*JB*/
 41.1981 +                                tempw=getword2f();
 41.1982 +                                if (flags&C_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1983 +                                cycles -= timing_bnt;
 41.1984 +                                break;
 41.1985 +                                case 0x83: /*JNB*/
 41.1986 +                                tempw=getword2f();
 41.1987 +                                if (!(flags&C_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1988 +                                cycles -= timing_bnt;
 41.1989 +                                break;
 41.1990 +                                case 0x84: /*JE*/
 41.1991 +                                tempw=getword2f();
 41.1992 +                                if (flags&Z_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1993 +                                cycles -= timing_bnt;
 41.1994 +                                break;
 41.1995 +                                case 0x85: /*JNE*/
 41.1996 +                                tempw=getword2f();
 41.1997 +                                if (!(flags&Z_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.1998 +                                cycles -= timing_bnt;
 41.1999 +                                break;
 41.2000 +                                case 0x86: /*JBE*/
 41.2001 +                                tempw=getword2f();
 41.2002 +                                if (flags&(C_FLAG|Z_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2003 +                                cycles -= timing_bnt;
 41.2004 +                                break;
 41.2005 +                                case 0x87: /*JNBE*/
 41.2006 +                                tempw=getword2f();
 41.2007 +                                if (!(flags&(C_FLAG|Z_FLAG))) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2008 +                                cycles -= timing_bnt;
 41.2009 +                                break;
 41.2010 +                                case 0x88: /*JS*/
 41.2011 +                                tempw=getword2f();
 41.2012 +                                if (flags&N_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2013 +                                cycles -= timing_bnt;
 41.2014 +                                break;
 41.2015 +                                case 0x89: /*JNS*/
 41.2016 +                                tempw=getword2f();
 41.2017 +                                if (!(flags&N_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2018 +                                cycles -= timing_bnt;
 41.2019 +                                break;
 41.2020 +                                case 0x8A: /*JP*/
 41.2021 +                                tempw=getword2f();
 41.2022 +                                if (flags&P_FLAG) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2023 +                                cycles -= timing_bnt;
 41.2024 +                                break;
 41.2025 +                                case 0x8B: /*JNP*/
 41.2026 +                                tempw=getword2f();
 41.2027 +                                if (!(flags&P_FLAG)) { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2028 +                                cycles -= timing_bnt;
 41.2029 +                                break;
 41.2030 +                                case 0x8C: /*JL*/
 41.2031 +                                tempw=getword2f();
 41.2032 +                                temp=(flags&N_FLAG)?1:0;
 41.2033 +                                temp2=(flags&V_FLAG)?1:0;
 41.2034 +                                if (temp!=temp2)  { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2035 +                                cycles -= timing_bnt;
 41.2036 +                                break;
 41.2037 +                                case 0x8D: /*JNL*/
 41.2038 +                                tempw=getword2f();
 41.2039 +                                temp=(flags&N_FLAG)?1:0;
 41.2040 +                                temp2=(flags&V_FLAG)?1:0;
 41.2041 +                                if (temp==temp2)  { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2042 +                                cycles -= timing_bnt;
 41.2043 +                                break;
 41.2044 +                                case 0x8E: /*JLE*/
 41.2045 +                                tempw=getword2f();
 41.2046 +                                temp=(flags&N_FLAG)?1:0;
 41.2047 +                                temp2=(flags&V_FLAG)?1:0;
 41.2048 +                                if ((flags&Z_FLAG) || (temp!=temp2))  { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2049 +                                cycles -= timing_bnt;
 41.2050 +                                break;
 41.2051 +                                case 0x8F: /*JNLE*/
 41.2052 +                                tempw=getword2f();
 41.2053 +                                temp=(flags&N_FLAG)?1:0;
 41.2054 +                                temp2=(flags&V_FLAG)?1:0;
 41.2055 +                                if (!((flags&Z_FLAG) || (temp!=temp2)))  { pc+=(int16_t)tempw; cycles-=timing_bt; }
 41.2056 +                                cycles -= timing_bnt;
 41.2057 +                                break;
 41.2058 +
 41.2059 +                                case 0x90: /*SETO*/
 41.2060 +                                fetchea2();
 41.2061 +                                seteab((flags&V_FLAG)?1:0);
 41.2062 +                                cycles-=4;
 41.2063 +                                break;
 41.2064 +                                case 0x91: /*SETNO*/
 41.2065 +                                fetchea2();
 41.2066 +                                seteab((flags&V_FLAG)?0:1);
 41.2067 +                                cycles-=4;
 41.2068 +                                break;
 41.2069 +                                case 0x92: /*SETC*/
 41.2070 +                                fetchea2();
 41.2071 +                                seteab((flags&C_FLAG)?1:0);
 41.2072 +                                cycles-=4;
 41.2073 +                                break;
 41.2074 +                                case 0x93: /*SETAE*/
 41.2075 +                                fetchea2();
 41.2076 +                                seteab((flags&C_FLAG)?0:1);
 41.2077 +                                cycles-=4;
 41.2078 +                                break;
 41.2079 +                                case 0x94: /*SETZ*/
 41.2080 +                                fetchea2();
 41.2081 +                                seteab((flags&Z_FLAG)?1:0);
 41.2082 +                                cycles-=4;
 41.2083 +                                break;
 41.2084 +                                case 0x95: /*SETNZ*/
 41.2085 +                                fetchea2();
 41.2086 +                                seteab((flags&Z_FLAG)?0:1);
 41.2087 +                                cycles-=4;
 41.2088 +                                break;
 41.2089 +                                case 0x96: /*SETBE*/
 41.2090 +                                fetchea2();
 41.2091 +                                seteab((flags&(C_FLAG|Z_FLAG))?1:0);
 41.2092 +                                cycles-=4;
 41.2093 +                                break;
 41.2094 +                                case 0x97: /*SETNBE*/
 41.2095 +                                fetchea2();
 41.2096 +                                seteab((flags&(C_FLAG|Z_FLAG))?0:1);
 41.2097 +                                cycles-=4;
 41.2098 +                                break;
 41.2099 +                                case 0x98: /*SETS*/
 41.2100 +                                fetchea2();
 41.2101 +                                seteab((flags&N_FLAG)?1:0);
 41.2102 +                                cycles-=4;
 41.2103 +                                break;
 41.2104 +                                case 0x99: /*SETNS*/
 41.2105 +                                fetchea2();
 41.2106 +                                seteab((flags&N_FLAG)?0:1);
 41.2107 +                                cycles-=4;
 41.2108 +                                break;
 41.2109 +                                case 0x9A: /*SETP*/
 41.2110 +                                fetchea2();
 41.2111 +                                seteab((flags&P_FLAG)?1:0);
 41.2112 +                                cycles-=4;
 41.2113 +                                break;
 41.2114 +                                case 0x9B: /*SETNP*/
 41.2115 +                                fetchea2();
 41.2116 +                                seteab((flags&P_FLAG)?0:1);
 41.2117 +                                cycles-=4;
 41.2118 +                                break;
 41.2119 +                                case 0x9C: /*SETL*/
 41.2120 +                                fetchea2();
 41.2121 +                                temp=(flags&N_FLAG)?1:0;
 41.2122 +                                temp2=(flags&V_FLAG)?1:0;
 41.2123 +                                seteab(temp^temp2);
 41.2124 +                                cycles-=4;
 41.2125 +                                break;
 41.2126 +                                case 0x9D: /*SETGE*/
 41.2127 +                                fetchea2();
 41.2128 +                                temp=(flags&N_FLAG)?1:0;
 41.2129 +                                temp2=(flags&V_FLAG)?1:0;
 41.2130 +                                seteab((temp^temp2)?0:1);
 41.2131 +                                cycles-=4;
 41.2132 +                                break;
 41.2133 +                                case 0x9E: /*SETLE*/
 41.2134 +                                fetchea2();
 41.2135 +                                temp=(flags&N_FLAG)?1:0;
 41.2136 +                                temp2=(flags&V_FLAG)?1:0;
 41.2137 +                                seteab(((temp^temp2) || (flags&Z_FLAG))?1:0);
 41.2138 +                                cycles-=4;
 41.2139 +                                break;
 41.2140 +                                case 0x9F: /*SETNLE*/
 41.2141 +                                fetchea2();
 41.2142 +                                temp=(flags&N_FLAG)?1:0;
 41.2143 +                                temp2=(flags&V_FLAG)?1:0;
 41.2144 +                                seteab(((temp^temp2) || (flags&Z_FLAG))?0:1);
 41.2145 +                                cycles-=4;
 41.2146 +                                break;
 41.2147 +
 41.2148 +                                case 0xA0: /*PUSH FS*/
 41.2149 +                                if (ssegs) ss=oldss;
 41.2150 +                                if (stack32)
 41.2151 +                                {
 41.2152 +                                        writememw(ss,ESP-2,FS); if (abrt) break;
 41.2153 +                                        ESP-=2;
 41.2154 +                                }
 41.2155 +                                else
 41.2156 +                                {
 41.2157 +                                        writememw(ss,((SP-2)&0xFFFF),FS); if (abrt) break;
 41.2158 +                                        SP-=2;
 41.2159 +                                }
 41.2160 +                                cycles-=2;
 41.2161 +                                break;
 41.2162 +                                case 0xA1: /*POP FS*/
 41.2163 +                                if (ssegs) ss=oldss;
 41.2164 +                                if (stack32)
 41.2165 +                                {
 41.2166 +                                        tempw=readmemw(ss,ESP);         if (abrt) break;
 41.2167 +                                        loadseg(tempw,&_fs);            if (abrt) break;
 41.2168 +                                        ESP+=2;
 41.2169 +                                }
 41.2170 +                                else
 41.2171 +                                {
 41.2172 +                                        tempw=readmemw(ss,SP);          if (abrt) break;
 41.2173 +                                        loadseg(tempw,&_fs);            if (abrt) break;
 41.2174 +                                        SP+=2;
 41.2175 +                                }
 41.2176 +                                cycles-=(is486)?3:7;
 41.2177 +                                break;
 41.2178 +                                case 0xA3: /*BT r16*/
 41.2179 +                                fetchea2();
 41.2180 +                                eaaddr+=((regs[reg].w/16)*2); eal_r = 0;
 41.2181 +                                tempw=geteaw(); if (abrt) break;
 41.2182 +                                if (tempw&(1<<(regs[reg].w&15))) flags|=C_FLAG;
 41.2183 +                                else                             flags&=~C_FLAG;
 41.2184 +                                cycles-=3;
 41.2185 +                                break;
 41.2186 +                                case 0xA4: /*SHLD imm*/
 41.2187 +                                fetchea2();
 41.2188 +                                temp=readmemb(cs,pc)&31; pc++;
 41.2189 +                                if (temp)
 41.2190 +                                {
 41.2191 +                                        tempw=geteaw(); if (abrt) break;
 41.2192 +                                        tempc=((tempw<<(temp-1))&0x8000)?1:0;
 41.2193 +                                        templ=(tempw<<16)|regs[reg].w;
 41.2194 +                                        if (temp<=16) tempw=templ>>(16-temp);
 41.2195 +                                        else          tempw=(templ<<temp)>>16;
 41.2196 +                                        seteaw(tempw); if (abrt) break;
 41.2197 +                                        setznp16(tempw);
 41.2198 +                                        if (tempc) flags|=C_FLAG;
 41.2199 +                                }
 41.2200 +                                cycles-=3;
 41.2201 +                                break;
 41.2202 +                                case 0xA5: /*SHLD CL*/
 41.2203 +                                fetchea2();
 41.2204 +                                temp=CL&31;
 41.2205 +                                if (temp)
 41.2206 +                                {
 41.2207 +                                        tempw=geteaw(); if (abrt) break;
 41.2208 +                                        tempc=((tempw<<(temp-1))&0x8000)?1:0;
 41.2209 +                                        templ=(tempw<<16)|regs[reg].w;
 41.2210 +                                        if (temp<=16) tempw=templ>>(16-temp);
 41.2211 +                                        else          tempw=(templ<<temp)>>16;
 41.2212 +                                        seteaw(tempw); if (abrt) break;
 41.2213 +                                        setznp16(tempw);
 41.2214 +                                        if (tempc) flags|=C_FLAG;
 41.2215 +                                }
 41.2216 +                                cycles-=3;
 41.2217 +                                break;
 41.2218 +                                case 0xA8: /*PUSH GS*/
 41.2219 +                                if (ssegs) ss=oldss;
 41.2220 +                                if (stack32)
 41.2221 +                                {
 41.2222 +                                        writememw(ss,ESP-2,GS); if (abrt) break;
 41.2223 +                                        ESP-=2;
 41.2224 +                                }
 41.2225 +                                else
 41.2226 +                                {
 41.2227 +                                        writememw(ss,((SP-2)&0xFFFF),GS); if (abrt) break;
 41.2228 +                                        SP-=2;
 41.2229 +                                }
 41.2230 +                                cycles-=2;
 41.2231 +                                break;
 41.2232 +                                case 0xA9: /*POP GS*/
 41.2233 +                                if (ssegs) ss=oldss;
 41.2234 +                                if (stack32)
 41.2235 +                                {
 41.2236 +                                        tempw=readmemw(ss,ESP);         if (abrt) break;
 41.2237 +                                        loadseg(tempw,&_gs);            if (abrt) break;
 41.2238 +                                        ESP+=2;
 41.2239 +                                }
 41.2240 +                                else
 41.2241 +                                {
 41.2242 +                                        tempw=readmemw(ss,SP);          if (abrt) break;
 41.2243 +                                        loadseg(tempw,&_gs);            if (abrt) break;
 41.2244 +                                        SP+=2;
 41.2245 +                                }
 41.2246 +                                cycles-=(is486)?3:7;
 41.2247 +                                break;
 41.2248 +                                case 0xAB: /*BTS r16*/
 41.2249 +                                fetchea2();
 41.2250 +                                eaaddr+=((regs[reg].w/16)*2); eal_r = eal_w = 0;
 41.2251 +                                tempw=geteaw(); if (abrt) break;
 41.2252 +                                tempc=(tempw&(1<<(regs[reg].w&15)))?1:0;
 41.2253 +                                tempw|=(1<<(regs[reg].w&15));
 41.2254 +                                seteaw(tempw); if (abrt) break;
 41.2255 +                                if (tempc) flags|=C_FLAG;
 41.2256 +                                else       flags&=~C_FLAG;
 41.2257 +                                cycles-=6;
 41.2258 +                                break;
 41.2259 +                                case 0xAC: /*SHRD imm*/
 41.2260 +                                fetchea2();
 41.2261 +                                temp=readmemb(cs,pc)&31; pc++;
 41.2262 +                                if (temp)
 41.2263 +                                {
 41.2264 +                                        tempw=geteaw(); if (abrt) break;
 41.2265 +                                        tempc=(tempw>>(temp-1))&1;
 41.2266 +                                        templ=tempw|(regs[reg].w<<16);
 41.2267 +                                        tempw=templ>>temp;
 41.2268 +                                        seteaw(tempw); if (abrt) break;
 41.2269 +                                        setznp16(tempw);
 41.2270 +                                        if (tempc) flags|=C_FLAG;
 41.2271 +                                }
 41.2272 +                                cycles-=3;
 41.2273 +                                break;
 41.2274 +                                case 0xAD: /*SHRD CL*/
 41.2275 +                                fetchea2();
 41.2276 +                                temp=CL&31;
 41.2277 +                                if (temp)
 41.2278 +                                {
 41.2279 +                                        tempw=geteaw(); if (abrt) break;
 41.2280 +                                        tempc=(tempw>>(temp-1))&1;
 41.2281 +                                        templ=tempw|(regs[reg].w<<16);
 41.2282 +                                        tempw=templ>>temp;
 41.2283 +                                        seteaw(tempw); if (abrt) break;
 41.2284 +                                        setznp16(tempw);
 41.2285 +                                        if (tempc) flags|=C_FLAG;
 41.2286 +                                }
 41.2287 +                                cycles-=3;
 41.2288 +                                break;
 41.2289 +
 41.2290 +                                case 0xAF: /*IMUL reg16,rm16*/
 41.2291 +                                fetchea2();
 41.2292 +                                templ=(int32_t)(int16_t)regs[reg].w*(int32_t)(int16_t)geteaw();
 41.2293 +                                if (abrt) break;
 41.2294 +                                regs[reg].w=templ&0xFFFF;
 41.2295 +                                if ((templ>>16) && (templ>>16)!=0xFFFF) flags|=C_FLAG|V_FLAG;
 41.2296 +                                else                                    flags&=~(C_FLAG|V_FLAG);
 41.2297 +                                cycles-=18;
 41.2298 +                                break;
 41.2299 +
 41.2300 +                                case 0xB0: /*CMPXCHG rm8, reg8*/
 41.2301 +                                if (!is486) goto inv16;
 41.2302 +                                fetchea2();
 41.2303 +                                temp = geteab();
 41.2304 +                                setsub8(AL, temp);
 41.2305 +                                if (AL == temp) seteab(getr8(reg));
 41.2306 +                                else             AL = temp;
 41.2307 +                                cycles -= (mod == 3) ? 6 : 10;
 41.2308 +                                break;
 41.2309 +                                case 0xB1: /*CMPXCHG rm16, reg16*/
 41.2310 +                                if (!is486) goto inv16;
 41.2311 +                                fetchea2();
 41.2312 +                                tempw = geteaw();
 41.2313 +                                setsub16(AX, tempw);
 41.2314 +                                if (AX == tempw) seteaw(regs[reg].w);
 41.2315 +                                else             AX = tempw;
 41.2316 +                                cycles -= (mod == 3) ? 6 : 10;
 41.2317 +                                break;
 41.2318 +                                
 41.2319 +                                case 0xB3: /*BTR r16*/
 41.2320 +                                fetchea2();
 41.2321 +                                eaaddr+=((regs[reg].w/16)*2); eal_r = eal_w = 0;
 41.2322 +                                tempw=geteaw(); if (abrt) break;
 41.2323 +                                tempc=tempw&(1<<(regs[reg].w&15));
 41.2324 +                                tempw&=~(1<<(regs[reg].w&15));
 41.2325 +                                seteaw(tempw); if (abrt) break;
 41.2326 +                                if (tempc) flags|=C_FLAG;
 41.2327 +                                else       flags&=~C_FLAG;
 41.2328 +                                cycles-=6;
 41.2329 +                                break;
 41.2330 +
 41.2331 +                                case 0xB2: /*LSS*/
 41.2332 +                                fetchea2();
 41.2333 +                                tempw2=readmemw(easeg,eaaddr);
 41.2334 +                                tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break;
 41.2335 +                                loadseg(tempw,&_ss); if (abrt) break;
 41.2336 +                                regs[reg].w=tempw2;
 41.2337 +                                oldss=ss;
 41.2338 +                                cycles-=7;
 41.2339 +                                break;
 41.2340 +                                case 0xB4: /*LFS*/
 41.2341 +                                fetchea2();
 41.2342 +                                tempw2=readmemw(easeg,eaaddr);
 41.2343 +                                tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break;
 41.2344 +                                loadseg(tempw,&_fs); if (abrt) break;
 41.2345 +                                regs[reg].w=tempw2;
 41.2346 +                                cycles-=7;
 41.2347 +                                break;
 41.2348 +                                case 0xB5: /*LGS*/
 41.2349 +                                fetchea2();
 41.2350 +                                tempw2=readmemw(easeg,eaaddr);
 41.2351 +                                tempw=readmemw(easeg,(eaaddr+2)); if (abrt) break;
 41.2352 +                                loadseg(tempw,&_gs); if (abrt) break;
 41.2353 +                                regs[reg].w=tempw2;
 41.2354 +                                cycles-=7;
 41.2355 +                                break;
 41.2356 +
 41.2357 +                                case 0xB6: /*MOVZX b*/
 41.2358 +                                fetchea2();
 41.2359 +                                tempw=geteab(); if (abrt) break;
 41.2360 +                                regs[reg].w=tempw;
 41.2361 +                                cycles-=3;
 41.2362 +                                break;
 41.2363 +                                case 0xB7: /*MOVZX w*/
 41.2364 +                                fetchea2(); /*Slightly pointless?*/
 41.2365 +                                tempw=geteaw(); if (abrt) break;
 41.2366 +                                regs[reg].w=tempw;
 41.2367 +                                cycles-=3;
 41.2368 +                                break;
 41.2369 +                                case 0xBE: /*MOVSX b*/
 41.2370 +                                fetchea2();
 41.2371 +                                tempw=geteab(); if (abrt) break;
 41.2372 +                                if (tempw&0x80) tempw|=0xFF00;
 41.2373 +                                regs[reg].w=tempw;
 41.2374 +                                cycles-=3;
 41.2375 +                                break;
 41.2376 +
 41.2377 +                                case 0xBA: /*MORE?!?!?!*/
 41.2378 +                                fetchea2();
 41.2379 +                                switch (rmdat&0x38)
 41.2380 +                                {
 41.2381 +                                        case 0x20: /*BT w,imm*/
 41.2382 +                                        tempw=geteaw();
 41.2383 +                                        temp=readmemb(cs,pc); pc++; if (abrt) break;
 41.2384 +                                        if (tempw&(1<<temp)) flags|=C_FLAG;
 41.2385 +                                        else                 flags&=~C_FLAG;
 41.2386 +                                        cycles-=6;
 41.2387 +                                        break;
 41.2388 +                                        case 0x28: /*BTS w,imm*/
 41.2389 +                                        tempw=geteaw();
 41.2390 +                                        temp=readmemb(cs,pc); pc++; if (abrt) break;
 41.2391 +                                        tempc=(tempw&(1<<temp))?1:0;
 41.2392 +                                        tempw|=(1<<temp);
 41.2393 +                                        seteaw(tempw);  if (abrt) break;
 41.2394 +                                        if (tempc) flags|=C_FLAG;
 41.2395 +                                        else       flags&=~C_FLAG;
 41.2396 +                                        cycles-=6;
 41.2397 +                                        break;
 41.2398 +                                        case 0x30: /*BTR w,imm*/
 41.2399 +                                        tempw=geteaw();
 41.2400 +                                        temp=readmemb(cs,pc); pc++; if (abrt) break;
 41.2401 +                                        tempc=(tempw&(1<<temp))?1:0;
 41.2402 +                                        tempw&=~(1<<temp);
 41.2403 +                                        seteaw(tempw); if (abrt) break;
 41.2404 +                                        if (tempc) flags|=C_FLAG;
 41.2405 +                                        else       flags&=~C_FLAG;
 41.2406 +                                        cycles-=6;
 41.2407 +                                        break;
 41.2408 +                                        case 0x38: /*BTC w,imm*/
 41.2409 +                                        tempw=geteaw();
 41.2410 +                                        temp=readmemb(cs,pc); pc++; if (abrt) break;
 41.2411 +                                        tempc=(tempw&(1<<temp))?1:0;
 41.2412 +                                        tempw^=(1<<temp);
 41.2413 +                                        seteaw(tempw); if (abrt) break;
 41.2414 +                                        if (tempc) flags|=C_FLAG;
 41.2415 +                                        else       flags&=~C_FLAG;
 41.2416 +                                        cycles-=6;
 41.2417 +                                        break;
 41.2418 +
 41.2419 +                                        default:
 41.2420 +                                        pclog("Bad 0F BA opcode %02X\n",rmdat&0x38);
 41.2421 +                                        pc=oldpc;
 41.2422 +                                        x86illegal();
 41.2423 +                                        break;
 41.2424 +                                }
 41.2425 +                                break;
 41.2426 +
 41.2427 +                                case 0xBC: /*BSF w*/
 41.2428 +                                fetchea2();
 41.2429 +                                tempw = geteaw(); if (abrt) break;
 41.2430 +                                if (!tempw)
 41.2431 +                                {
 41.2432 +//                                        regs[reg].w=0;
 41.2433 +                                        flags |= Z_FLAG;
 41.2434 +                                }
 41.2435 +                                else
 41.2436 +                                {
 41.2437 +                                        for (tempi = 0; tempi < 16; tempi++)
 41.2438 +                                        {
 41.2439 +                                                cycles -= (is486) ? 1 : 3;
 41.2440 +                                                if (tempw & (1 << tempi))
 41.2441 +                                                {
 41.2442 +                                                        flags &= ~Z_FLAG;
 41.2443 +                                                        regs[reg].w = tempi;
 41.2444 +                                                        break;
 41.2445 +                                                }
 41.2446 +                                        }
 41.2447 +                                }
 41.2448 +                                cycles -= (is486) ? 6 : 10;
 41.2449 +                                break;
 41.2450 +                                case 0xBD: /*BSR w*/
 41.2451 +                                fetchea2();
 41.2452 +                                tempw = geteaw(); if (abrt) break;
 41.2453 +                                if (!tempw)
 41.2454 +                                {
 41.2455 +//                                        regs[reg].w=0;
 41.2456 +                                        flags |= Z_FLAG;
 41.2457 +                                }
 41.2458 +                                else
 41.2459 +                                {
 41.2460 +                                        for (tempi = 15; tempi >= 0; tempi--)
 41.2461 +                                        {
 41.2462 +                                                cycles -= 3;
 41.2463 +                                                if (tempw & (1 << tempi))
 41.2464 +                                                {
 41.2465 +                                                        flags &= ~Z_FLAG;
 41.2466 +                                                        regs[reg].w = tempi;
 41.2467 +                                                        break;
 41.2468 +                                                }
 41.2469 +                                        }
 41.2470 +                                }
 41.2471 +                                cycles -= (is486) ? 6 : 10;
 41.2472 +                                break;
 41.2473 +
 41.2474 +                                case 0xA2: /*CPUID*/
 41.2475 +                                if (CPUID)
 41.2476 +                                {
 41.2477 +                                        cpu_CPUID();
 41.2478 +                                        cycles-=9;
 41.2479 +                                        break;
 41.2480 +                                }
 41.2481 +                                goto inv16;
 41.2482 +
 41.2483 +                                case 0xC0: /*XADD b*/
 41.2484 +                                pclog("XADDb 16\n");
 41.2485 +                                fetchea2();
 41.2486 +                                temp=geteab(); if (abrt) break;
 41.2487 +                                seteab(temp+getr8(reg)); if (abrt) break;
 41.2488 +                                setadd8(temp,getr8(reg));
 41.2489 +                                setr8(reg,temp);
 41.2490 +                                break;
 41.2491 +                                case 0xC1: /*XADD w*/
 41.2492 +                                pclog("XADDw 16\n");
 41.2493 +                                fetchea2();
 41.2494 +                                tempw=geteaw(); if (abrt) break;
 41.2495 +                                seteaw(tempw+regs[reg].w); if (abrt) break;
 41.2496 +                                setadd16(tempw,regs[reg].w);
 41.2497 +                                regs[reg].w=tempw;
 41.2498 +                                break;
 41.2499 +
 41.2500 +                                case 0xA6: /*XBTS/CMPXCHG486*/
 41.2501 +                                pclog("CMPXCHG486\n");
 41.2502 +//                                output=1;
 41.2503 +                                case 0xFF: /*Invalid - Windows 3.1 syscall trap?*/
 41.2504 +                                inv16:
 41.2505 +                                pc-=2;
 41.2506 +                                if (msw&1)
 41.2507 +                                {
 41.2508 +                                        pmodeint(6,0);
 41.2509 +                                }
 41.2510 +                                else
 41.2511 +                                {
 41.2512 +                                        if (ssegs) ss=oldss;
 41.2513 +                                        if (stack32)
 41.2514 +                                        {
 41.2515 +                                                writememw(ss,ESP-2,flags);
 41.2516 +                                                writememw(ss,ESP-4,CS);
 41.2517 +                                                writememw(ss,ESP-6,pc);
 41.2518 +                                                ESP-=6;
 41.2519 +                                        }
 41.2520 +                                        else
 41.2521 +                                        {
 41.2522 +                                                writememw(ss,((SP-2)&0xFFFF),flags);
 41.2523 +                                                writememw(ss,((SP-4)&0xFFFF),CS);
 41.2524 +                                                writememw(ss,((SP-6)&0xFFFF),pc);
 41.2525 +                                                SP-=6;
 41.2526 +                                        }
 41.2527 +                                        addr=6<<2;
 41.2528 +                                        flags&=~I_FLAG;
 41.2529 +                                        flags&=~T_FLAG;
 41.2530 +                                        oxpc=pc;
 41.2531 +                                        pc=readmemw(0,addr);
 41.2532 +                                        loadcs(readmemw(0,addr+2));
 41.2533 +                                }
 41.2534 +                                cycles-=70;
 41.2535 +                                break;
 41.2536 +
 41.2537 +                                default:
 41.2538 +                                pclog("Bad 16-bit 0F opcode %02X 386 %i\n",temp,ins);
 41.2539 +                                pc=oldpc;
 41.2540 +                                x86illegal();
 41.2541 +                                break;
 41.2542 +                        }
 41.2543 +                        break;
 41.2544 +
 41.2545 +                        case 0x10F: case 0x30F:
 41.2546 +                        temp=fetchdat&0xFF/*readmemb(cs+pc)*/; pc++;
 41.2547 +                        opcode2=temp;
 41.2548 +                        switch (temp)
 41.2549 +                        {
 41.2550 +                                case 0:
 41.2551 +                                if (!(cr0&1) || (eflags&VM_FLAG)) goto inv32;
 41.2552 +                                fetchea2();
 41.2553 +//                                pclog("32-bit op %02X\n",rmdat&0x38);
 41.2554 +                                switch (rmdat&0x38)
 41.2555 +                                {
 41.2556 +                                        case 0x00: /*SLDT*/
 41.2557 +                                        NOTRM
 41.2558 +                                        seteaw(ldt.seg);
 41.2559 +                                        cycles-=4;
 41.2560 +                                        break;
 41.2561 +                                        case 0x08: /*STR*/
 41.2562 +                                        NOTRM
 41.2563 +                                        seteaw(tr.seg);
 41.2564 +                                        cycles-=4;
 41.2565 +                                        break;
 41.2566 +                                        case 0x10: /*LLDT*/
 41.2567 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.2568 +                                        {
 41.2569 +                                                pclog("Invalid LLDT32!\n");
 41.2570 +                                                x86gpf(NULL,0);
 41.2571 +                                                break;
 41.2572 +                                        }
 41.2573 +                                        NOTRM
 41.2574 +                                        ldt.seg=geteaw(); if (abrt) break;
 41.2575 +                                        templ=(ldt.seg&~7)+gdt.base;
 41.2576 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
 41.2577 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
 41.2578 +                                        if (abrt) break;
 41.2579 +                                        ldt.limit=templ3;
 41.2580 +                                        ldt.base=templ2;
 41.2581 +                                        ldt.access=readmemb(0,templ+6);
 41.2582 +                                        if (readmemb(0,templ+6)&0x80)
 41.2583 +                                        {
 41.2584 +                                                ldt.limit<<=12;
 41.2585 +                                                ldt.limit|=0xFFF;
 41.2586 +                                        }
 41.2587 +//                                        /*if (output==3) */pclog("LLDT32 %04X %08X %04X\n",ldt.seg,ldt.base,ldt.limit,readmeml(0,templ),readmeml(0,templ+4));
 41.2588 +                                        cycles-=20;
 41.2589 +                                        break;
 41.2590 +                                        case 0x18: /*LTR*/
 41.2591 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.2592 +                                        {
 41.2593 +                                                pclog("Invalid LTR32!\n");
 41.2594 +                                                x86gpf(NULL,0);
 41.2595 +                                                break;
 41.2596 +                                        }
 41.2597 +                                        NOTRM
 41.2598 +                                        tempw=geteaw(); if (abrt) break;
 41.2599 +                                        tr.seg=tempw;
 41.2600 +                                        templ=(tempw&~7)+gdt.base;
 41.2601 +                                        templ3=readmemw(0,templ)+((readmemb(0,templ+6)&0xF)<<16);
 41.2602 +                                        templ2=(readmemw(0,templ+2))|(readmemb(0,templ+4)<<16)|(readmemb(0,templ+7)<<24);
 41.2603 +                                        temp=readmemb(0,templ+5);
 41.2604 +                                        if (abrt) break;
 41.2605 +                                        tr.seg=tempw;
 41.2606 +                                        tr.limit=templ3;
 41.2607 +                                        tr.access=readmemb(0,templ+6);
 41.2608 +                                        if (readmemb(0,templ+6)&0x80)
 41.2609 +                                        {
 41.2610 +                                                tr.limit<<=12;
 41.2611 +                                                tr.limit|=0xFFF;
 41.2612 +                                        }
 41.2613 +                                        tr.base=templ2;
 41.2614 +//                                        pclog("TR base = %08X\n",templ2);
 41.2615 +                                        tr.access=temp;
 41.2616 +                                        cycles-=20;
 41.2617 +                                        break;
 41.2618 +
 41.2619 +                                        case 0x20: /*VERR*/
 41.2620 +                                        NOTRM
 41.2621 +                                        tempw=geteaw(); if (abrt) break;
 41.2622 +                                        flags&=~Z_FLAG;
 41.2623 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
 41.2624 +                                        cpl_override=1;
 41.2625 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.2626 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.2627 +                                        cpl_override=0;
 41.2628 +                                        if (abrt) break;
 41.2629 +                                        if (!(tempw2&0x1000)) tempi=0;
 41.2630 +                                        if ((tempw2&0xC00)!=0xC00) /*Exclude conforming code segments*/
 41.2631 +                                        {
 41.2632 +                                                tempw3=(tempw2>>13)&3; /*Check permissions*/
 41.2633 +                                                if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.2634 +                                        }
 41.2635 +                                        if ((tempw2&0x0800) && !(tempw2&0x0200)) tempi=0; /*Non-readable code*/
 41.2636 +                                        if (tempi) flags|=Z_FLAG;
 41.2637 +                                        cycles-=20;
 41.2638 +                                        break;
 41.2639 +                                        case 0x28: /*VERW*/
 41.2640 +                                        NOTRM
 41.2641 +                                        tempw=geteaw(); if (abrt) break;
 41.2642 +                                        flags&=~Z_FLAG;
 41.2643 +                                        if (!(tempw&0xFFFC)) break; /*Null selector*/
 41.2644 +                                        cpl_override=1;
 41.2645 +                                        tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.2646 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.2647 +                                        cpl_override=0;
 41.2648 +                                        if (abrt) break;
 41.2649 +                                        if (!(tempw2&0x1000)) tempi=0;
 41.2650 +                                        tempw3=(tempw2>>13)&3; /*Check permissions*/
 41.2651 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.2652 +                                        if (tempw2&0x0800) tempi=0; /*Code*/
 41.2653 +                                        else if (!(tempw2&0x0200)) tempi=0; /*Read-only data*/
 41.2654 +                                        if (tempi) flags|=Z_FLAG;
 41.2655 +                                        cycles-=20;
 41.2656 +                                        break;
 41.2657 +
 41.2658 +                                        default:
 41.2659 +                                        pclog("Bad 0F 00 opcode %02X\n",rmdat&0x38);
 41.2660 +                                        pc=oldpc;
 41.2661 +                                        x86illegal();
 41.2662 +                                        break;
 41.2663 +                                }
 41.2664 +                                break;
 41.2665 +                                case 1:
 41.2666 +                                fetchea2();
 41.2667 +                                switch (rmdat&0x38)
 41.2668 +                                {
 41.2669 +                                        case 0x00: /*SGDT*/
 41.2670 +                                        seteaw(gdt.limit);
 41.2671 +                                        writememl(easeg,eaaddr+2,gdt.base);
 41.2672 +                                        cycles-=7;
 41.2673 +                                        break;
 41.2674 +                                        case 0x08: /*SIDT*/
 41.2675 +                                        seteaw(idt.limit);
 41.2676 +                                        writememl(easeg,eaaddr+2,idt.base);
 41.2677 +                                        cycles-=7;
 41.2678 +                                        break;
 41.2679 +                                        case 0x10: /*LGDT*/
 41.2680 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.2681 +                                        {
 41.2682 +                                                pclog("Invalid LGDT32!\n");
 41.2683 +                                                x86gpf(NULL,0);
 41.2684 +                                                break;
 41.2685 +                                        }
 41.2686 +                                        tempw=geteaw();
 41.2687 +                                        templ=readmeml(easeg,eaaddr+2);
 41.2688 +                                        if (abrt) break;
 41.2689 +                                        gdt.limit=tempw;
 41.2690 +                                        gdt.base=templ;
 41.2691 +//                                        pclog("LGDT32 %08X %04X\n",gdt.base,gdt.limit);
 41.2692 +                                        cycles-=11;
 41.2693 +                                        break;
 41.2694 +                                        case 0x18: /*LIDT*/
 41.2695 +                                        if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.2696 +                                        {
 41.2697 +                                                pclog("Invalid LIDT32!\n");
 41.2698 +                                                x86gpf(NULL,0);
 41.2699 +                                                break;
 41.2700 +                                        }
 41.2701 +                                        tempw=geteaw();
 41.2702 +                                        templ=readmeml(easeg,eaaddr+2);
 41.2703 +                                        idt.limit=tempw;
 41.2704 +                                        idt.base=templ;
 41.2705 +//                                        pclog("LIDT32 %08X %08X\n",idt.base,readmeml(0,easeg+eaaddr+2));
 41.2706 +                                        cycles-=11;
 41.2707 +                                        break;
 41.2708 +                                        case 0x20: /*SMSW*/
 41.2709 +                                        if (mod<3) seteaw(cr0);
 41.2710 +                                        else       seteal(cr0); /*Apparently this is the case!*/
 41.2711 +//                                        pclog("SMSW32 %04X(%06X):%04X\n",CS,cs,pc);
 41.2712 +                                        cycles-=2;
 41.2713 +                                        break;
 41.2714 +                                        
 41.2715 +                                        case 0x30: /*LMSW*/
 41.2716 +                                        if ((CPL || eflags&VM_FLAG) && (msw&1))
 41.2717 +                                        {
 41.2718 +                                                pclog("LMSW - ring not zero!\n");
 41.2719 +                                                x86gpf(NULL,0);
 41.2720 +                                                break;
 41.2721 +                                        }
 41.2722 +                                        tempw=geteaw(); if (abrt) break;
 41.2723 +                                        if (msw&1) tempw|=1;
 41.2724 +                                        msw=tempw;
 41.2725 +                                        break;
 41.2726 +
 41.2727 +                                        case 0x38: /*INVLPG*/
 41.2728 +                                        if (is486)
 41.2729 +                                        {
 41.2730 +                                                if ((CPL || eflags&VM_FLAG) && (cr0&1))
 41.2731 +                                                {
 41.2732 +                                                        pclog("Invalid INVLPG!\n");
 41.2733 +                                                        x86gpf(NULL,0);
 41.2734 +                                                        break;
 41.2735 +                                                }
 41.2736 +                                                if (output) pclog("INVLPG %08X + %08X\n", eaaddr, ds);
 41.2737 +                                                mmu_invalidate(ds + eaaddr);
 41.2738 +                                                cycles-=12;
 41.2739 +                                                break;
 41.2740 +                                        }
 41.2741 +
 41.2742 +
 41.2743 +                                        default:
 41.2744 +                                        pclog("Bad 0F 01 opcode %02X\n",rmdat&0x38);
 41.2745 +                                        pc=oldpc;
 41.2746 +                                        x86illegal();
 41.2747 +                                        break;
 41.2748 +                                }
 41.2749 +                                break;
 41.2750 +
 41.2751 +                                case 2: /*LAR*/
 41.2752 +                                NOTRM
 41.2753 +                                fetchea2();
 41.2754 +                                tempw=geteaw(); if (abrt) break;
 41.2755 +//                                pclog("LAR seg %04X\n",tempw);
 41.2756 +                                if (!(tempw&0xFFFC)) { flags&=~Z_FLAG; break; } /*Null selector*/
 41.2757 +                                cpl_override=1;
 41.2758 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.2759 +                                tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.2760 +                                cpl_override=0;
 41.2761 +                                if (abrt) break;
 41.2762 +                                flags&=~Z_FLAG;
 41.2763 +//                                pclog("tempw2 %04X  %i  %04X %04X\n",tempw2,tempi,ldt.limit,gdt.limit);
 41.2764 +                                if ((tempw2&0x1F00)==0x000) tempi=0;
 41.2765 +                                if ((tempw2&0x1F00)==0x800) tempi=0;
 41.2766 +                                if ((tempw2&0x1F00)==0xA00) tempi=0;
 41.2767 +                                if ((tempw2&0x1F00)==0xD00) tempi=0;
 41.2768 +                                if ((tempw2&0x1C00)<0x1C00) /*Exclude conforming code segments*/
 41.2769 +                                {
 41.2770 +                                        tempw3=(tempw2>>13)&3;
 41.2771 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.2772 +                                }
 41.2773 +                                if (tempi)
 41.2774 +                                {
 41.2775 +                                        flags|=Z_FLAG;
 41.2776 +                                        cpl_override=1;
 41.2777 +                                        regs[reg].l=readmeml(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4)&0xFFFF00;
 41.2778 +                                        cpl_override=0;
 41.2779 +                                }
 41.2780 +                                cycles-=11;
 41.2781 +                                break;
 41.2782 +
 41.2783 +                                case 3: /*LSL*/
 41.2784 +                                NOTRM
 41.2785 +                                fetchea2();
 41.2786 +                                tempw=geteaw(); if (abrt) break;
 41.2787 +                                if (output) pclog("LSL %04X\n",tempw);
 41.2788 +                                if (!(tempw&0xFFFC)) { flags&=~Z_FLAG; break; } /*Null selector*/
 41.2789 +                                cpl_override=1;
 41.2790 +                                tempi=(tempw&~7)<((tempw&4)?ldt.limit:gdt.limit);
 41.2791 +                                if (output) pclog("In range? %i\n",tempi);
 41.2792 +                                if (tempi)
 41.2793 +                                {
 41.2794 +                                        tempw2=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+4);
 41.2795 +                                        if (output) pclog("segdat[2] = %04X\n",tempw2);
 41.2796 +                                }
 41.2797 +                                cpl_override=0;
 41.2798 +                                if (abrt) break;
 41.2799 +                                flags&=~Z_FLAG;
 41.2800 +                                if ((tempw2&0x1400)==0x400) tempi=0; /*Interrupt or trap or call gate*/
 41.2801 +                                if ((tempw2&0x1F00)==0x000) tempi=0; /*Invalid*/
 41.2802 +                                if ((tempw2&0x1F00)==0xA00) tempi=0; /*Invalid*/
 41.2803 +                                if ((tempw2&0x1C00)!=0x1C00) /*Exclude conforming code segments*/
 41.2804 +                                {
 41.2805 +                                        tempw3=(tempw2>>13)&3;
 41.2806 +                                        if (tempw3<CPL || tempw3<(tempw&3)) tempi=0;
 41.2807 +                                }
 41.2808 +                                if (output) pclog("Final tempi %i\n",tempi);
 41.2809 +                                if (tempi)
 41.2810 +                                {
 41.2811 +                                        flags|=Z_FLAG;
 41.2812 +                                        cpl_override=1;
 41.2813 +                                        regs[reg].l=readmemw(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7));
 41.2814 +                                        regs[reg].l|=(readmemb(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+6)&0xF)<<16;
 41.2815 +                                        if (readmemb(0,((tempw&4)?ldt.base:gdt.base)+(tempw&~7)+6)&0x80)
 41.2816 +                                        {
 41.2817 +                                                regs[reg].l<<=12;
 41.2818 +                                                regs[reg].l|=0xFFF;
 41.2819 +                                        }
 41.2820 +                                        cpl_override=0;
 41.2821 +                                }
 41.2822 +                                cycles-=10;
 41.2823 +                                break;
 41.2824 +
 41.2825 +                                case 6: /*CLTS*/
 41.2826 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2827 +                                {
 41.2828 +                                        pclog("Can't CLTS\n");
 41.2829 +                                        x86gpf(NULL,0);
 41.2830 +                                        break;
 41.2831 +                                }
 41.2832 +                                cr0&=~8;
 41.2833 +                                cycles-=5;
 41.2834 +                                break;
 41.2835 +
 41.2836 +                                case 8: /*INVD*/
 41.2837 +                                if (!is486) goto inv32;
 41.2838 +                                cycles-=1000;
 41.2839 +                                break;
 41.2840 +                                case 9: /*WBINVD*/
 41.2841 +                                if (!is486) goto inv32;
 41.2842 +                                cycles-=10000;
 41.2843 +                                break;
 41.2844 +
 41.2845 +                                case 0x20: /*MOV reg32,CRx*/
 41.2846 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2847 +                                {
 41.2848 +                                        pclog("Can't load from CRx\n");
 41.2849 +                                        x86gpf(NULL,0);
 41.2850 +                                        break;
 41.2851 +                                }
 41.2852 +                                fetchea2();
 41.2853 +                                switch (reg)
 41.2854 +                                {
 41.2855 +                                        case 0:
 41.2856 +                                        regs[rm].l=cr0;//&~2;
 41.2857 +                                        if (is486) regs[rm].l|=0x10; /*ET hardwired on 486*/
 41.2858 +                                        break;
 41.2859 +                                        case 2:
 41.2860 +                                        regs[rm].l=cr2;
 41.2861 +                                        break;
 41.2862 +                                        case 3:
 41.2863 +                                        regs[rm].l=cr3;
 41.2864 +                                        break;
 41.2865 +                                        default:
 41.2866 +                                        pclog("Bad read of CR%i %i\n",rmdat&7,reg);
 41.2867 +                                        pc=oldpc;
 41.2868 +                                        x86illegal();
 41.2869 +                                        break;
 41.2870 +                                }
 41.2871 +                                cycles-=6;
 41.2872 +                                break;
 41.2873 +                                case 0x21: /*MOV reg32,DRx*/
 41.2874 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2875 +                                {
 41.2876 +                                        pclog("Can't load from DRx\n");
 41.2877 +                                        x86gpf(NULL,0);
 41.2878 +                                        break;
 41.2879 +                                }
 41.2880 +                                fetchea2();
 41.2881 +                                regs[rm].l=0;
 41.2882 +                                cycles-=6;
 41.2883 +                                break;
 41.2884 +                                case 0x22: /*MOV CRx,reg32*/
 41.2885 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2886 +                                {
 41.2887 +                                        pclog("Can't load CRx\n");
 41.2888 +                                        x86gpf(NULL,0);
 41.2889 +                                        break;
 41.2890 +                                }
 41.2891 +                                fetchea2();
 41.2892 +                                switch (reg)
 41.2893 +                                {
 41.2894 +                                        case 0:
 41.2895 +                                        //if ((cr0^regs[rm].l)>>31) flushmmucache();
 41.2896 +                                        if ((regs[rm].l^cr0) & 0x80000001) flushmmucache();
 41.2897 +                                        cr0=regs[rm].l;//&~2;
 41.2898 +                                        if (cpu_16bitbus) cr0 |= 0x10;
 41.2899 +//                                        if (cs<0xF0000 && cr0&1) output=3;
 41.2900 +                                        if (cr0&0x80000000)
 41.2901 +                                        {
 41.2902 +                                        }
 41.2903 +                                        else mmu_perm=4;
 41.2904 +                                        break;
 41.2905 +                                        case 2:
 41.2906 +                                        cr2=regs[rm].l;
 41.2907 +                                        break;
 41.2908 +                                        case 3:
 41.2909 +                                        cr3=regs[rm].l&~0xFFF;
 41.2910 +//                                        pclog("Loading CR3 with %08X at %08X:%08X\n",cr3,cs,pc);
 41.2911 +                                        flushmmucache();
 41.2912 +                                        break;
 41.2913 +                                        default:
 41.2914 +                                        pclog("Bad load CR%i\n",reg);
 41.2915 +                                        pc=oldpc;
 41.2916 +                                        x86illegal();
 41.2917 +                                        break;
 41.2918 +                                }
 41.2919 +                                cycles-=10;
 41.2920 +                                break;
 41.2921 +                                case 0x23: /*MOV DRx,reg32*/
 41.2922 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2923 +                                {
 41.2924 +                                        pclog("Can't load DRx\n");
 41.2925 +                                        x86gpf(NULL,0);
 41.2926 +                                        break;
 41.2927 +                                }
 41.2928 +                                fetchea2();
 41.2929 +                                cycles-=6;
 41.2930 +                                break;
 41.2931 +                                case 0x24: /*MOV reg32,TRx*/
 41.2932 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2933 +                                {
 41.2934 +                                        pclog("Can't load from TRx\n");
 41.2935 +                                        x86gpf(NULL,0);
 41.2936 +                                        break;
 41.2937 +                                }
 41.2938 +                                fetchea2();
 41.2939 +                                regs[rm].l=0;
 41.2940 +                                cycles-=6;
 41.2941 +                                break;
 41.2942 +                                case 0x26: /*MOV TRx,reg32*/
 41.2943 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.2944 +                                {
 41.2945 +                                        pclog("Can't load TRx\n");
 41.2946 +                                        x86gpf(NULL,0);
 41.2947 +                                        break;
 41.2948 +                                }
 41.2949 +                                fetchea2();
 41.2950 +                                cycles-=6;
 41.2951 +                                break;
 41.2952 +
 41.2953 +                                case 0x80: /*JO*/
 41.2954 +                                templ=getlong(); if (abrt) break;
 41.2955 +                                if (flags&V_FLAG) { pc+=templ; cycles-=((is486)?2:4); }
 41.2956 +                                cycles-=((is486)?1:3);
 41.2957 +                                break;
 41.2958 +                                case 0x81: /*JNO*/
 41.2959 +                                templ=getlong(); if (abrt) break;
 41.2960 +                                if (!(flags&V_FLAG)) { pc+=templ; cycles-=((is486)?2:4); }
 41.2961 +                                cycles-=((is486)?1:3);
 41.2962 +                                break;
 41.2963 +                                case 0x82: /*JB*/
 41.2964 +                                templ=getlong(); if (abrt) break;
 41.2965 +                                if (flags&C_FLAG) { pc+=templ; cycles-=((is486)?2:4); }
 41.2966 +                                cycles-=((is486)?1:3);
 41.2967 +                                break;
 41.2968 +                                case 0x83: /*JNB*/
 41.2969 +                                templ=getlong(); if (abrt) break;
 41.2970 +                                if (!(flags&C_FLAG)) { pc+=templ; cycles-=((is486)?2:4); }
 41.2971 +                                cycles-=((is486)?1:3);
 41.2972 +                                break;
 41.2973 +                                case 0x84: /*JE*/
 41.2974 +                                templ=getlong(); if (abrt) break;
 41.2975 +                                if (flags&Z_FLAG) pc+=templ;
 41.2976 +                                cycles-=4;
 41.2977 +                                break;
 41.2978 +                                case 0x85: /*JNE*/
 41.2979 +                                templ=getlong(); if (abrt) break;
 41.2980 +                                if (!(flags&Z_FLAG)) pc+=templ;
 41.2981 +                                cycles-=4;
 41.2982 +                                break;
 41.2983 +                                case 0x86: /*JBE*/
 41.2984 +                                templ=getlong(); if (abrt) break;
 41.2985 +                                if (flags&(C_FLAG|Z_FLAG)) { pc+=templ; cycles-=((is486)?2:4); }
 41.2986 +                                cycles-=((is486)?1:3);
 41.2987 +                                break;
 41.2988 +                                case 0x87: /*JNBE*/
 41.2989 +                                templ=getlong(); if (abrt) break;
 41.2990 +                                if (!(flags&(C_FLAG|Z_FLAG))) { pc+=templ; cycles-=((is486)?2:4); }
 41.2991 +                                cycles-=((is486)?1:3);
 41.2992 +                                break;
 41.2993 +                                case 0x88: /*JS*/
 41.2994 +                                templ=getlong(); if (abrt) break;
 41.2995 +                                if (flags&N_FLAG) pc+=templ;
 41.2996 +                                cycles-=4;
 41.2997 +                                break;
 41.2998 +                                case 0x89: /*JNS*/
 41.2999 +                                templ=getlong(); if (abrt) break;
 41.3000 +                                if (!(flags&N_FLAG)) pc+=templ;
 41.3001 +                                cycles-=4;
 41.3002 +                                break;
 41.3003 +                                case 0x8A: /*JP*/
 41.3004 +                                templ=getlong(); if (abrt) break;
 41.3005 +                                if (flags&P_FLAG) pc+=templ;
 41.3006 +                                cycles-=4;
 41.3007 +                                break;
 41.3008 +                                case 0x8B: /*JNP*/
 41.3009 +                                templ=getlong(); if (abrt) break;
 41.3010 +                                if (!(flags&P_FLAG)) pc+=templ;
 41.3011 +                                cycles-=4;
 41.3012 +                                break;
 41.3013 +                                case 0x8C: /*JL*/
 41.3014 +                                templ=getlong(); if (abrt) break;
 41.3015 +                                temp=(flags&N_FLAG)?1:0;
 41.3016 +                                temp2=(flags&V_FLAG)?1:0;
 41.3017 +                                if (temp!=temp2)  { pc+=templ; cycles-=((is486)?2:4); }
 41.3018 +                                cycles-=((is486)?1:3);
 41.3019 +                                break;
 41.3020 +                                case 0x8D: /*JNL*/
 41.3021 +                                templ=getlong(); if (abrt) break;
 41.3022 +                                temp=(flags&N_FLAG)?1:0;
 41.3023 +                                temp2=(flags&V_FLAG)?1:0;
 41.3024 +                                if (temp==temp2)  { pc+=templ; cycles-=((is486)?2:4); }
 41.3025 +                                cycles-=((is486)?1:3);
 41.3026 +                                break;
 41.3027 +                                case 0x8E: /*JLE*/
 41.3028 +                                templ=getlong(); if (abrt) break;
 41.3029 +                                temp=(flags&N_FLAG)?1:0;
 41.3030 +                                temp2=(flags&V_FLAG)?1:0;
 41.3031 +                                if ((flags&Z_FLAG) || (temp!=temp2))  { pc+=templ; cycles-=((is486)?2:4); }
 41.3032 +                                cycles-=((is486)?1:3);
 41.3033 +                                break;
 41.3034 +                                case 0x8F: /*JNLE*/
 41.3035 +                                templ=getlong(); if (abrt) break;
 41.3036 +                                temp=(flags&N_FLAG)?1:0;
 41.3037 +                                temp2=(flags&V_FLAG)?1:0;
 41.3038 +                                if (!((flags&Z_FLAG) || (temp!=temp2)))  { pc+=templ; cycles-=((is486)?2:4); }
 41.3039 +                                cycles-=((is486)?1:3);
 41.3040 +                                break;
 41.3041 +
 41.3042 +                                case 0x90: /*SETO*/
 41.3043 +                                fetchea2();
 41.3044 +                                seteab((flags&V_FLAG)?1:0);
 41.3045 +                                cycles-=4;
 41.3046 +                                break;
 41.3047 +                                case 0x91: /*SETNO*/
 41.3048 +                                fetchea2();
 41.3049 +                                seteab((flags&V_FLAG)?0:1);
 41.3050 +                                cycles-=4;
 41.3051 +                                break;
 41.3052 +                                case 0x92: /*SETC*/
 41.3053 +                                fetchea2();
 41.3054 +                                seteab((flags&C_FLAG)?1:0);
 41.3055 +                                cycles-=4;
 41.3056 +                                break;
 41.3057 +                                case 0x93: /*SETAE*/
 41.3058 +                                fetchea2();
 41.3059 +                                seteab((flags&C_FLAG)?0:1);
 41.3060 +                                cycles-=4;
 41.3061 +                                break;
 41.3062 +                                case 0x94: /*SETZ*/
 41.3063 +                                fetchea2();
 41.3064 +                                seteab((flags&Z_FLAG)?1:0);
 41.3065 +                                cycles-=4;
 41.3066 +                                break;
 41.3067 +                                case 0x95: /*SETNZ*/
 41.3068 +                                fetchea2();
 41.3069 +                                seteab((flags&Z_FLAG)?0:1);
 41.3070 +                                cycles-=4;
 41.3071 +                                break;
 41.3072 +                                case 0x96: /*SETBE*/
 41.3073 +                                fetchea2();
 41.3074 +                                seteab((flags&(C_FLAG|Z_FLAG))?1:0);
 41.3075 +                                cycles-=4;
 41.3076 +                                break;
 41.3077 +                                case 0x97: /*SETNBE*/
 41.3078 +                                fetchea2();
 41.3079 +                                seteab((flags&(C_FLAG|Z_FLAG))?0:1);
 41.3080 +                                cycles-=4;
 41.3081 +                                break;
 41.3082 +                                case 0x98: /*SETS*/
 41.3083 +                                fetchea2();
 41.3084 +                                seteab((flags&N_FLAG)?1:0);
 41.3085 +                                cycles-=4;
 41.3086 +                                break;
 41.3087 +                                case 0x99: /*SETNS*/
 41.3088 +                                fetchea2();
 41.3089 +                                seteab((flags&N_FLAG)?0:1);
 41.3090 +                                cycles-=4;
 41.3091 +                                break;
 41.3092 +                                case 0x9A: /*SETP*/
 41.3093 +                                fetchea2();
 41.3094 +                                seteab((flags&P_FLAG)?1:0);
 41.3095 +                                cycles-=4;
 41.3096 +                                break;
 41.3097 +                                case 0x9B: /*SETNP*/
 41.3098 +                                fetchea2();
 41.3099 +                                seteab((flags&P_FLAG)?0:1);
 41.3100 +                                cycles-=4;
 41.3101 +                                break;
 41.3102 +                                case 0x9C: /*SETL*/
 41.3103 +                                fetchea2();
 41.3104 +                                temp=(flags&N_FLAG)?1:0;
 41.3105 +                                temp2=(flags&V_FLAG)?1:0;
 41.3106 +                                seteab(temp^temp2);
 41.3107 +                                cycles-=4;
 41.3108 +                                break;
 41.3109 +                                case 0x9D: /*SETGE*/
 41.3110 +                                fetchea2();
 41.3111 +                                temp=(flags&N_FLAG)?1:0;
 41.3112 +                                temp2=(flags&V_FLAG)?1:0;
 41.3113 +                                seteab((temp^temp2)?0:1);
 41.3114 +                                cycles-=4;
 41.3115 +                                break;
 41.3116 +                                case 0x9E: /*SETLE*/
 41.3117 +                                fetchea2();
 41.3118 +                                temp=(flags&N_FLAG)?1:0;
 41.3119 +                                temp2=(flags&V_FLAG)?1:0;
 41.3120 +                                seteab(((temp^temp2) || (flags&Z_FLAG))?1:0);
 41.3121 +                                cycles-=4;
 41.3122 +                                break;
 41.3123 +                                case 0x9F: /*SETNLE*/
 41.3124 +                                fetchea2();
 41.3125 +                                temp=(flags&N_FLAG)?1:0;
 41.3126 +                                temp2=(flags&V_FLAG)?1:0;
 41.3127 +                                seteab(((temp^temp2) || (flags&Z_FLAG))?0:1);
 41.3128 +                                cycles-=4;
 41.3129 +                                break;
 41.3130 +
 41.3131 +                                case 0xA0: /*PUSH FS*/
 41.3132 +                                if (ssegs) ss=oldss;
 41.3133 +                                if (stack32)
 41.3134 +                                {
 41.3135 +                                        writememl(ss,ESP-4,FS); if (abrt) break;
 41.3136 +                                        ESP-=4;
 41.3137 +                                }
 41.3138 +                                else
 41.3139 +                                {
 41.3140 +                                        writememl(ss,((SP-4)&0xFFFF),FS); if (abrt) break;
 41.3141 +                                        SP-=4;
 41.3142 +                                }
 41.3143 +                                cycles-=2;
 41.3144 +                                break;
 41.3145 +                                case 0xA1: /*POP FS*/
 41.3146 +                                if (ssegs) ss=oldss;
 41.3147 +                                if (stack32)
 41.3148 +                                {
 41.3149 +                                        tempw=readmemw(ss,ESP);         if (abrt) break;
 41.3150 +                                        loadseg(tempw,&_fs);            if (abrt) break;
 41.3151 +                                        ESP+=4;
 41.3152 +                                }
 41.3153 +                                else
 41.3154 +                                {
 41.3155 +                                        tempw=readmemw(ss,SP);          if (abrt) break;
 41.3156 +                                        loadseg(tempw,&_fs);            if (abrt) break;
 41.3157 +                                        SP+=4;
 41.3158 +                                }
 41.3159 +                                cycles-=(is486)?3:7;
 41.3160 +                                break;
 41.3161 +                                case 0xA8: /*PUSH GS*/
 41.3162 +                                if (ssegs) ss=oldss;
 41.3163 +                                if (stack32)
 41.3164 +                                {
 41.3165 +                                        writememl(ss,ESP-4,GS); if (abrt) break;
 41.3166 +                                        ESP-=4;
 41.3167 +                                }
 41.3168 +                                else
 41.3169 +                                {
 41.3170 +                                        writememl(ss,((SP-4)&0xFFFF),GS); if (abrt) break;
 41.3171 +                                        SP-=4;
 41.3172 +                                }
 41.3173 +                                cycles-=2;
 41.3174 +                                break;
 41.3175 +                                case 0xA9: /*POP GS*/
 41.3176 +                                if (ssegs) ss=oldss;
 41.3177 +                                if (stack32)
 41.3178 +                                {
 41.3179 +                                        tempw=readmemw(ss,ESP);         if (abrt) break;
 41.3180 +                                        loadseg(tempw,&_gs);            if (abrt) break;
 41.3181 +                                        ESP+=4;
 41.3182 +                                }
 41.3183 +                                else
 41.3184 +                                {
 41.3185 +                                        tempw=readmemw(ss,SP);          if (abrt) break;
 41.3186 +                                        loadseg(tempw,&_gs);            if (abrt) break;
 41.3187 +                                        SP+=4;
 41.3188 +                                }
 41.3189 +                                cycles-=(is486)?3:7;
 41.3190 +                                break;
 41.3191 +
 41.3192 +                                case 0xA3: /*BT r32*/
 41.3193 +                                fetchea2();
 41.3194 +                                eaaddr+=((regs[reg].l/32)*4); eal_r = 0;
 41.3195 +                                templ=geteal(); if (abrt) break;
 41.3196 +                                if (templ&(1<<(regs[reg].l&31))) flags|=C_FLAG;
 41.3197 +                                else                             flags&=~C_FLAG;
 41.3198 +                                cycles-=3;
 41.3199 +                                break;
 41.3200 +                                case 0xA4: /*SHLD imm*/
 41.3201 +                                fetchea2();
 41.3202 +                                temp=readmemb(cs,pc)&31; pc++;
 41.3203 +                                if (temp)
 41.3204 +                                {
 41.3205 +                                        templ=geteal(); if (abrt) break;
 41.3206 +                                        tempc=((templ<<(temp-1))&0x80000000)?1:0;
 41.3207 +                                        templ=(templ<<temp)|(regs[reg].l>>(32-temp));
 41.3208 +                                        seteal(templ); if (abrt) break;
 41.3209 +                                        setznp32(templ);
 41.3210 +                                        if (tempc) flags|=C_FLAG;
 41.3211 +                                }
 41.3212 +                                cycles-=3;
 41.3213 +                                break;
 41.3214 +                                case 0xA5: /*SHLD CL*/
 41.3215 +                                fetchea2();
 41.3216 +                                temp=CL&31;
 41.3217 +                                if (temp)
 41.3218 +                                {
 41.3219 +                                        templ=geteal(); if (abrt) break;
 41.3220 +                                        tempc=((templ<<(temp-1))&0x80000000)?1:0;
 41.3221 +                                        templ=(templ<<temp)|(regs[reg].l>>(32-temp));
 41.3222 +                                        seteal(templ); if (abrt) break;
 41.3223 +                                        setznp32(templ);
 41.3224 +                                        if (tempc) flags|=C_FLAG;
 41.3225 +                                }
 41.3226 +                                cycles-=3;
 41.3227 +                                break;
 41.3228 +                                case 0xAB: /*BTS r32*/
 41.3229 +                                fetchea2();
 41.3230 +                                eaaddr+=((regs[reg].l/32)*4); eal_r = eal_w = 0;
 41.3231 +                                templ=geteal(); if (abrt) break;
 41.3232 +                                tempc=(templ&(1<<(regs[reg].l&31)))?1:0;
 41.3233 +                                templ|=(1<<(regs[reg].l&31));
 41.3234 +                                seteal(templ); if (abrt) break;
 41.3235 +                                if (tempc) flags|=C_FLAG;
 41.3236 +                                else       flags&=~C_FLAG;
 41.3237 +                                cycles-=6;
 41.3238 +                                break;
 41.3239 +                                case 0xAC: /*SHRD imm*/
 41.3240 +                                fetchea2();
 41.3241 +                                temp=readmemb(cs,pc)&31; pc++;
 41.3242 +                                if (temp)
 41.3243 +                                {
 41.3244 +                                        templ=geteal(); if (abrt) break;
 41.3245 +                                        tempc=(templ>>(temp-1))&1;
 41.3246 +                                        templ=(templ>>temp)|(regs[reg].l<<(32-temp));
 41.3247 +                                        seteal(templ); if (abrt) break;
 41.3248 +                                        setznp32(templ);
 41.3249 +                                        if (tempc) flags|=C_FLAG;
 41.3250 +                                }
 41.3251 +                                cycles-=3;
 41.3252 +                                break;
 41.3253 +                                case 0xAD: /*SHRD CL*/
 41.3254 +                                fetchea2();
 41.3255 +                                temp=CL&31;
 41.3256 +                                if (temp)
 41.3257 +                                {
 41.3258 +                                        templ=geteal(); if (abrt) break;
 41.3259 +                                        tempc=(templ>>(temp-1))&1;
 41.3260 +                                        templ=(templ>>temp)|(regs[reg].l<<(32-temp));
 41.3261 +                                        seteal(templ); if (abrt) break;
 41.3262 +                                        setznp32(templ);
 41.3263 +                                        if (tempc) flags|=C_FLAG;
 41.3264 +                                }
 41.3265 +                                cycles-=3;
 41.3266 +                                break;
 41.3267 +
 41.3268 +                                case 0xAF: /*IMUL reg32,rm32*/
 41.3269 +                                fetchea2();
 41.3270 +                                temp64=(int64_t)(int32_t)regs[reg].l*(int64_t)(int32_t)geteal();
 41.3271 +                                if (abrt) break;
 41.3272 +                                regs[reg].l=temp64&0xFFFFFFFF;
 41.3273 +                                if ((temp64>>32) && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG;
 41.3274 +                                else                                          flags&=~(C_FLAG|V_FLAG);
 41.3275 +                                cycles-=30;
 41.3276 +                                break;
 41.3277 +
 41.3278 +                                case 0xB0: /*CMPXCHG rm8, reg8*/
 41.3279 +                                if (!is486) goto inv32;
 41.3280 +                                fetchea2();
 41.3281 +                                temp = geteab();
 41.3282 +                                setsub8(AL, temp);
 41.3283 +                                if (AL == temp) seteab(getr8(reg));
 41.3284 +                                else            AL = temp;
 41.3285 +                                cycles -= (mod == 3) ? 6 : 10;
 41.3286 +                                break;
 41.3287 +                                case 0xB1: /*CMPXCHG rm32, reg32*/
 41.3288 +                                if (!is486) goto inv32;
 41.3289 +                                fetchea2();
 41.3290 +                                templ = geteal();
 41.3291 +                                setsub32(EAX, templ);
 41.3292 +                                if (EAX == templ) seteal(regs[reg].l);
 41.3293 +                                else              EAX = templ;
 41.3294 +                                cycles -= (mod == 3) ? 6 : 10;
 41.3295 +                                break;
 41.3296 +
 41.3297 +                                case 0xB3: /*BTR r32*/
 41.3298 +                                fetchea2();
 41.3299 +                                eaaddr+=((regs[reg].l/32)*4); eal_r = eal_w = 0;
 41.3300 +                                templ=geteal(); if (abrt) break;
 41.3301 +                                tempc=(templ&(1<<(regs[reg].l&31)))?1:0;
 41.3302 +                                templ&=~(1<<(regs[reg].l&31));
 41.3303 +                                seteal(templ); if (abrt) break;
 41.3304 +                                if (tempc) flags|=C_FLAG;
 41.3305 +                                else       flags&=~C_FLAG;
 41.3306 +                                cycles-=6;
 41.3307 +                                break;
 41.3308 +
 41.3309 +                                case 0xB2: /*LSS*/
 41.3310 +                                fetchea2();
 41.3311 +                                templ=readmeml(easeg,eaaddr);     
 41.3312 +                                tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break;
 41.3313 +                                loadseg(tempw,&_ss);              if (abrt) break;
 41.3314 +                                regs[reg].l=templ;
 41.3315 +                                oldss=ss;
 41.3316 +                                cycles-=7;
 41.3317 +                                break;
 41.3318 +                                case 0xB4: /*LFS*/
 41.3319 +                                fetchea2();
 41.3320 +                                templ=readmeml(easeg,eaaddr);
 41.3321 +                                tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break;
 41.3322 +                                loadseg(tempw,&_fs);              if (abrt) break;
 41.3323 +                                regs[reg].l=templ;
 41.3324 +                                cycles-=7;
 41.3325 +                                break;
 41.3326 +                                case 0xB5: /*LGS*/
 41.3327 +                                fetchea2();
 41.3328 +                                templ=readmeml(easeg,eaaddr);
 41.3329 +                                tempw=readmemw(easeg,(eaaddr+4)); if (abrt) break;
 41.3330 +                                loadseg(tempw,&_gs);              if (abrt) break;
 41.3331 +                                regs[reg].l=templ;
 41.3332 +                                cycles-=7;
 41.3333 +                                break;
 41.3334 +
 41.3335 +                                case 0xB6: /*MOVZX b*/
 41.3336 +                                fetchea2();
 41.3337 +                                templ=geteab(); if (abrt) break;
 41.3338 +                                regs[reg].l=templ;
 41.3339 +                                cycles-=3;
 41.3340 +                                break;
 41.3341 +                                case 0xB7: /*MOVZX w*/
 41.3342 +                                fetchea2();
 41.3343 +                                templ=geteaw(); if (abrt) break;
 41.3344 +                                regs[reg].l=templ;
 41.3345 +                                cycles-=3;
 41.3346 +//                                if (pc==0x30B) output=1;
 41.3347 +                                break;
 41.3348 +
 41.3349 +                                case 0xBA: /*MORE?!?!?!*/
 41.3350 +                                fetchea2();
 41.3351 +                                switch (rmdat&0x38)
 41.3352 +                                {
 41.3353 +                                        case 0x20: /*BT l,imm*/
 41.3354 +                                        templ=geteal();
 41.3355 +                                        temp=readmemb(cs,pc); pc++;
 41.3356 +                                        if (abrt) break;
 41.3357 +                                        if (templ&(1<<temp)) flags|=C_FLAG;
 41.3358 +                                        else                 flags&=~C_FLAG;
 41.3359 +                                        cycles-=6;
 41.3360 +                                        break;
 41.3361 +                                        case 0x28: /*BTS l,imm*/
 41.3362 +                                        templ=geteal();
 41.3363 +                                        temp=readmemb(cs,pc); pc++;
 41.3364 +                                        if (abrt) break;
 41.3365 +                                        tempc=(templ&(1<<temp))?1:0;
 41.3366 +                                        templ|=(1<<temp);
 41.3367 +                                        seteal(templ); if (abrt) break;
 41.3368 +                                        if (tempc) flags|=C_FLAG;
 41.3369 +                                        else       flags&=~C_FLAG;
 41.3370 +                                        cycles-=6;
 41.3371 +                                        break;
 41.3372 +                                        case 0x30: /*BTR l,imm*/
 41.3373 +                                        templ=geteal();
 41.3374 +                                        temp=readmemb(cs,pc); pc++;
 41.3375 +                                        if (abrt) break;
 41.3376 +                                        tempc=(templ&(1<<temp))?1:0;
 41.3377 +                                        templ&=~(1<<temp);
 41.3378 +                                        seteal(templ); if (abrt) break;
 41.3379 +                                        if (tempc) flags|=C_FLAG;
 41.3380 +                                        else       flags&=~C_FLAG;
 41.3381 +                                        cycles-=6;
 41.3382 +                                        break;
 41.3383 +                                        case 0x38: /*BTC l,imm*/
 41.3384 +                                        templ=geteal();
 41.3385 +                                        temp=readmemb(cs,pc); pc++;
 41.3386 +                                        if (abrt) break;
 41.3387 +                                        tempc=(templ&(1<<temp))?1:0;
 41.3388 +                                        templ^=(1<<temp);
 41.3389 +                                        seteal(templ); if (abrt) break;
 41.3390 +                                        if (tempc) flags|=C_FLAG;
 41.3391 +                                        else       flags&=~C_FLAG;
 41.3392 +                                        cycles-=6;
 41.3393 +                                        break;
 41.3394 +
 41.3395 +                                        default:
 41.3396 +                                        pclog("Bad 32-bit 0F BA opcode %02X\n",rmdat&0x38);
 41.3397 +                                        pc=oldpc;
 41.3398 +                                        x86illegal();
 41.3399 +                                        break;
 41.3400 +                                }
 41.3401 +                                break;
 41.3402 +
 41.3403 +                                case 0xBB: /*BTC r32*/
 41.3404 +                                fetchea2();
 41.3405 +                                eaaddr+=((regs[reg].l/32)*4); eal_r = eal_w = 0;
 41.3406 +                                templ=geteal(); if (abrt) break;
 41.3407 +                                tempc=(templ&(1<<(regs[reg].l&31)))?1:0;
 41.3408 +                                templ^=(1<<(regs[reg].l&31));
 41.3409 +                                seteal(templ);  if (abrt) break;
 41.3410 +                                if (tempc) flags|=C_FLAG;
 41.3411 +                                else       flags&=~C_FLAG;
 41.3412 +                                cycles-=6;
 41.3413 +                                break;
 41.3414 +
 41.3415 +                                case 0xBC: /*BSF l*/
 41.3416 +                                fetchea2();
 41.3417 +                                templ=geteal(); if (abrt) break;
 41.3418 +                                if (!templ)
 41.3419 +                                {
 41.3420 +//                                        regs[reg].l=0;
 41.3421 +                                        flags|=Z_FLAG;
 41.3422 +                                }
 41.3423 +                                else
 41.3424 +                                {
 41.3425 +                                        for (tempi=0;tempi<32;tempi++)
 41.3426 +                                        {
 41.3427 +                                                cycles -= (is486) ? 1 : 3;
 41.3428 +                                                if (templ&(1<<tempi))
 41.3429 +                                                {
 41.3430 +                                                        flags&=~Z_FLAG;
 41.3431 +                                                        regs[reg].l=tempi;
 41.3432 +                                                        break;
 41.3433 +                                                }
 41.3434 +                                        }
 41.3435 +                                }
 41.3436 +                                cycles-=(is486)?6:10;
 41.3437 +                                break;
 41.3438 +                                case 0xBD: /*BSR l*/
 41.3439 +                                fetchea2();
 41.3440 +                                templ=geteal(); if (abrt) break;
 41.3441 +                                if (!templ)
 41.3442 +                                {
 41.3443 +//                                        regs[reg].l=0;
 41.3444 +                                        flags|=Z_FLAG;
 41.3445 +                                }
 41.3446 +                                else
 41.3447 +                                {
 41.3448 +                                        for (tempi=31;tempi>=0;tempi--)
 41.3449 +                                        {
 41.3450 +                                                cycles -= 3;
 41.3451 +                                                if (templ&(1<<tempi))
 41.3452 +                                                {
 41.3453 +                                                        flags&=~Z_FLAG;
 41.3454 +                                                        regs[reg].l=tempi;
 41.3455 +                                                        break;
 41.3456 +                                                }
 41.3457 +                                        }
 41.3458 +                                }
 41.3459 +                                cycles-=(is486)?6:10;
 41.3460 +                                break;
 41.3461 +
 41.3462 +                                case 0xBE: /*MOVSX b*/
 41.3463 +                                fetchea2();
 41.3464 +                                templ=geteab(); if (abrt) break;
 41.3465 +                                if (templ&0x80) templ|=0xFFFFFF00;
 41.3466 +                                regs[reg].l=templ;
 41.3467 +                                cycles-=3;
 41.3468 +                                break;
 41.3469 +                                case 0xBF: /*MOVSX w*/
 41.3470 +                                fetchea2();
 41.3471 +                                templ=geteaw(); if (abrt) break;
 41.3472 +                                if (templ&0x8000) templ|=0xFFFF0000;
 41.3473 +                                regs[reg].l=templ;
 41.3474 +                                cycles-=3;
 41.3475 +                                break;
 41.3476 +
 41.3477 +                                case 0xC0: /*XADD b*/
 41.3478 +                                pclog("XADDb 32\n");
 41.3479 +                                fetchea2();
 41.3480 +                                temp=geteab(); if (abrt) break;
 41.3481 +                                seteab(temp+getr8(reg)); if (abrt) break;
 41.3482 +                                setadd8(temp,getr8(reg));
 41.3483 +                                setr8(reg,temp);
 41.3484 +                                break;
 41.3485 +                                case 0xC1: /*XADD l*/
 41.3486 +//                                pclog("XADDl 32\n");
 41.3487 +                                fetchea2();
 41.3488 +                                templ=geteal(); if (abrt) break;
 41.3489 +                                templ2=regs[reg].l;
 41.3490 +//                                pclog("EAL %08X REG %08X\n",templ,templ2);
 41.3491 +                                seteal(templ+templ2); if (abrt) break;
 41.3492 +                                setadd32(templ,templ2);
 41.3493 +                                regs[reg].l=templ;
 41.3494 +//                                pclog("EAL %08X REG %08X\n",templ+templ2,regs[reg].l);
 41.3495 +                                break;
 41.3496 +
 41.3497 +                                case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*BSWAP*/
 41.3498 +                                case 0xCC: case 0xCD: case 0xCE: case 0xCF: /*486!!!*/
 41.3499 +                                regs[temp&7].l = (regs[temp&7].l>>24)|((regs[temp&7].l>>8)&0xFF00)|((regs[temp&7].l<<8)&0xFF0000)|((regs[temp&7].l<<24)&0xFF000000);
 41.3500 +                                cycles--;
 41.3501 +                                break;
 41.3502 +
 41.3503 +                                case 0xA2: /*CPUID*/
 41.3504 +                                if (CPUID)
 41.3505 +                                {
 41.3506 +                                        cpu_CPUID();
 41.3507 +                                        cycles-=9;
 41.3508 +                                        break;
 41.3509 +                                }
 41.3510 +                                goto inv32;
 41.3511 +                                
 41.3512 +                                case 0xFF:
 41.3513 +                                inv32:
 41.3514 +                                pclog("INV32!\n");
 41.3515 +                                default:
 41.3516 +                                pclog("Bad 32-bit 0F opcode %02X 386\n",temp);
 41.3517 +                                pc=oldpc;
 41.3518 +                                x86illegal();
 41.3519 +                                break;
 41.3520 +                        }
 41.3521 +                        break;
 41.3522 +
 41.3523 +                        case 0x10: case 0x110: case 0x210: case 0x310: /*ADC 8,reg*/
 41.3524 +                        fetchea();
 41.3525 +                        if (mod == 3)
 41.3526 +                        {
 41.3527 +                                temp  = getr8(rm);
 41.3528 +                                temp2 = getr8(reg);
 41.3529 +                                setadc8(temp, temp2);
 41.3530 +                                setr8(rm, temp + temp2 + tempc);
 41.3531 +                                cycles -= timing_rr;
 41.3532 +                        }
 41.3533 +                        else
 41.3534 +                        {
 41.3535 +                                temp  = geteab();               if (abrt) break;
 41.3536 +                                temp2 = getr8(reg);
 41.3537 +                                seteab(temp + temp2 + tempc);   if (abrt) break;
 41.3538 +                                setadc8(temp, temp2);
 41.3539 +                                cycles -= timing_mr;
 41.3540 +                        }
 41.3541 +                        break;
 41.3542 +                        case 0x11: case 0x211: /*ADC 16,reg*/
 41.3543 +                        fetchea();
 41.3544 +                        if (mod == 3)
 41.3545 +                        {
 41.3546 +                                setadc16(regs[rm].w, regs[reg].w);
 41.3547 +                                regs[rm].w += regs[reg].w + tempc;
 41.3548 +                                cycles -= timing_rr;
 41.3549 +                        }
 41.3550 +                        else
 41.3551 +                        {
 41.3552 +                                tempw  = geteaw();              if (abrt) break;
 41.3553 +                                tempw2 = regs[reg].w;
 41.3554 +                                seteaw(tempw + tempw2 + tempc); if (abrt) break;
 41.3555 +                                setadc16(tempw, tempw2);
 41.3556 +                                cycles -= timing_mr;
 41.3557 +                        }
 41.3558 +                        break;
 41.3559 +                        case 0x111: case 0x311: /*ADC 32,reg*/
 41.3560 +                        fetchea();
 41.3561 +                        if (mod == 3)
 41.3562 +                        {
 41.3563 +                                setadc32(regs[rm].l, regs[reg].l);
 41.3564 +                                regs[rm].l += regs[reg].l + tempc;
 41.3565 +                                cycles -= timing_rr;
 41.3566 +                        }
 41.3567 +                        else
 41.3568 +                        {
 41.3569 +                                templ  = geteal();              if (abrt) break;
 41.3570 +                                templ2 = regs[reg].l;
 41.3571 +                                seteal(templ + templ2 + tempc); if (abrt) break;
 41.3572 +                                setadc32(templ, templ2);
 41.3573 +                                cycles -= timing_mrl;
 41.3574 +                        }
 41.3575 +                        break;
 41.3576 +                        case 0x12: case 0x112: case 0x212: case 0x312: /*ADC reg,8*/
 41.3577 +                        fetchea();
 41.3578 +                        temp=geteab();                  if (abrt) break;
 41.3579 +                        setadc8(getr8(reg),temp);
 41.3580 +                        setr8(reg,getr8(reg)+temp+tempc);
 41.3581 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3582 +                        break;
 41.3583 +                        case 0x13: case 0x213: /*ADC reg,16*/
 41.3584 +                        fetchea();
 41.3585 +                        tempw=geteaw();                 if (abrt) break;
 41.3586 +                        setadc16(regs[reg].w,tempw);
 41.3587 +                        regs[reg].w+=tempw+tempc;
 41.3588 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3589 +                        break;
 41.3590 +                        case 0x113: case 0x313: /*ADC reg,32*/
 41.3591 +                        fetchea();
 41.3592 +                        templ=geteal();                 if (abrt) break;
 41.3593 +                        setadc32(regs[reg].l,templ);
 41.3594 +                        regs[reg].l+=templ+tempc;
 41.3595 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.3596 +                        break;
 41.3597 +                        case 0x14: case 0x114: case 0x214: case 0x314: /*ADC AL,#8*/
 41.3598 +                        tempw=getbytef();
 41.3599 +                        setadc8(AL,tempw);
 41.3600 +                        AL+=tempw+tempc;
 41.3601 +                        cycles -= timing_rr;
 41.3602 +                        break;
 41.3603 +                        case 0x15: case 0x215: /*ADC AX,#16*/
 41.3604 +                        tempw=getwordf();
 41.3605 +                        setadc16(AX,tempw);
 41.3606 +                        AX+=tempw+tempc;
 41.3607 +                        cycles -= timing_rr;
 41.3608 +                        break;
 41.3609 +                        case 0x115: case 0x315: /*ADC EAX,#32*/
 41.3610 +                        templ=getlong(); if (abrt) break;
 41.3611 +                        setadc32(EAX,templ);
 41.3612 +                        EAX+=templ+tempc;
 41.3613 +                        cycles -= timing_rr;
 41.3614 +                        break;
 41.3615 +
 41.3616 +                        case 0x16: case 0x216: /*PUSH SS*/
 41.3617 +                        if (ssegs) ss=oldss;
 41.3618 +                        if (stack32)
 41.3619 +                        {
 41.3620 +                                writememw(ss,ESP-2,SS);           if (abrt) break;
 41.3621 +                                ESP-=2;
 41.3622 +                        }
 41.3623 +                        else
 41.3624 +                        {
 41.3625 +                                writememw(ss,((SP-2)&0xFFFF),SS); if (abrt) break;
 41.3626 +                                SP-=2;
 41.3627 +                        }
 41.3628 +                        cycles-=2;
 41.3629 +                        break;
 41.3630 +                        case 0x116: case 0x316: /*PUSH SS*/
 41.3631 +                        if (ssegs) ss=oldss;
 41.3632 +                        if (stack32)
 41.3633 +                        {
 41.3634 +                                writememl(ss,ESP-4,SS);           if (abrt) break;
 41.3635 +                                ESP-=4;
 41.3636 +                        }
 41.3637 +                        else
 41.3638 +                        {
 41.3639 +                                writememl(ss,((SP-4)&0xFFFF),SS); if (abrt) break;
 41.3640 +                                SP-=4;
 41.3641 +                        }
 41.3642 +                        cycles-=2;
 41.3643 +                        break;
 41.3644 +                        case 0x17: case 0x217: /*POP SS*/
 41.3645 +                        if (ssegs) ss=oldss;
 41.3646 +                        if (stack32)
 41.3647 +                        {
 41.3648 +                                tempw=readmemw(ss,ESP); if (abrt) break;
 41.3649 +                                loadseg(tempw,&_ss); if (abrt) break;
 41.3650 +                                ESP+=2;
 41.3651 +                        }
 41.3652 +                        else
 41.3653 +                        {
 41.3654 +                                tempw=readmemw(ss,SP);  if (abrt) break;
 41.3655 +                                loadseg(tempw,&_ss); if (abrt) break;
 41.3656 +                                SP+=2;
 41.3657 +                        }
 41.3658 +                        cycles-=(is486)?3:7;
 41.3659 +                        break;
 41.3660 +                        case 0x117: case 0x317: /*POP SS*/
 41.3661 +                        if (ssegs) ss=oldss;
 41.3662 +                        if (stack32)
 41.3663 +                        {
 41.3664 +                                tempw=readmemw(ss,ESP); if (abrt) break;
 41.3665 +                                loadseg(tempw,&_ss); if (abrt) break;
 41.3666 +                                ESP+=4;
 41.3667 +                        }
 41.3668 +                        else
 41.3669 +                        {
 41.3670 +                                tempw=readmemw(ss,SP);  if (abrt) break;
 41.3671 +                                loadseg(tempw,&_ss); if (abrt) break;
 41.3672 +                                SP+=4;
 41.3673 +                        }
 41.3674 +                        cycles-=(is486)?3:7;
 41.3675 +                        break;
 41.3676 +
 41.3677 +                        case 0x18: case 0x118: case 0x218: case 0x318: /*SBB 8,reg*/
 41.3678 +                        fetchea();
 41.3679 +                        if (mod == 3)
 41.3680 +                        {
 41.3681 +                                temp  = getr8(rm);
 41.3682 +                                temp2 = getr8(reg);
 41.3683 +                                setsbc8(temp, temp2);
 41.3684 +                                setr8(rm, temp - (temp2 + tempc));
 41.3685 +                                cycles -= timing_rr;
 41.3686 +                        }
 41.3687 +                        else
 41.3688 +                        {
 41.3689 +                                temp  = geteab();                  if (abrt) break;
 41.3690 +                                temp2 = getr8(reg);
 41.3691 +                                seteab(temp - (temp2 + tempc));    if (abrt) break;
 41.3692 +                                setsbc8(temp, temp2);
 41.3693 +                                cycles -= timing_mr;
 41.3694 +                        }
 41.3695 +                        break;
 41.3696 +                        case 0x19: case 0x219: /*SBB 16,reg*/
 41.3697 +                        fetchea();
 41.3698 +                        if (mod == 3)
 41.3699 +                        {
 41.3700 +                                setsbc16(regs[rm].w, regs[reg].w);
 41.3701 +                                regs[rm].w -= (regs[reg].w + tempc);
 41.3702 +                                cycles -= timing_rr;
 41.3703 +                        }
 41.3704 +                        else
 41.3705 +                        {
 41.3706 +                                tempw  = geteaw();                 if (abrt) break;
 41.3707 +                                tempw2 = regs[reg].w;
 41.3708 +                                seteaw(tempw - (tempw2 + tempc));  if (abrt) break;
 41.3709 +                                setsbc16(tempw, tempw2);
 41.3710 +                                cycles -= timing_mr;
 41.3711 +                        }
 41.3712 +                        break;
 41.3713 +                        case 0x119: case 0x319: /*SBB 32,reg*/
 41.3714 +                        fetchea();
 41.3715 +                        if (mod == 3)
 41.3716 +                        {
 41.3717 +                                setsbc32(regs[rm].l, regs[reg].l);
 41.3718 +                                regs[rm].l -= (regs[reg].l + tempc);
 41.3719 +                                cycles -= timing_rr;
 41.3720 +                        }
 41.3721 +                        else
 41.3722 +                        {
 41.3723 +                                templ  = geteal();                 if (abrt) break;
 41.3724 +                                templ2 = regs[reg].l;
 41.3725 +                                seteal(templ - (templ2 + tempc));  if (abrt) break;
 41.3726 +                                setsbc32(templ, templ2);
 41.3727 +                                cycles -= timing_mrl;
 41.3728 +                        }
 41.3729 +                        break;
 41.3730 +                        case 0x1A: case 0x11A: case 0x21A: case 0x31A: /*SBB reg,8*/
 41.3731 +                        fetchea();
 41.3732 +                        temp=geteab();                  if (abrt) break;
 41.3733 +                        setsbc8(getr8(reg),temp);
 41.3734 +                        setr8(reg,getr8(reg)-(temp+tempc));
 41.3735 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3736 +                        break;
 41.3737 +                        case 0x1B: case 0x21B: /*SBB reg,16*/
 41.3738 +                        fetchea();
 41.3739 +                        tempw=geteaw();                 if (abrt) break;
 41.3740 +                        tempw2=regs[reg].w;
 41.3741 +                        setsbc16(tempw2,tempw);
 41.3742 +                        tempw2-=(tempw+tempc);
 41.3743 +                        regs[reg].w=tempw2;
 41.3744 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3745 +                        break;
 41.3746 +                        case 0x11B: case 0x31B: /*SBB reg,32*/
 41.3747 +                        fetchea();
 41.3748 +                        templ=geteal();                 if (abrt) break;
 41.3749 +                        templ2=regs[reg].l;
 41.3750 +                        setsbc32(templ2,templ);
 41.3751 +                        templ2-=(templ+tempc);
 41.3752 +                        regs[reg].l=templ2;
 41.3753 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.3754 +                        break;
 41.3755 +                        case 0x1C: case 0x11C: case 0x21C: case 0x31C: /*SBB AL,#8*/
 41.3756 +                        temp=getbytef();
 41.3757 +                        setsbc8(AL,temp);
 41.3758 +                        AL-=(temp+tempc);
 41.3759 +                        cycles-=(is486)?1:2;
 41.3760 +                        break;
 41.3761 +                        case 0x1D: case 0x21D: /*SBB AX,#16*/
 41.3762 +                        tempw=getwordf();
 41.3763 +                        setsbc16(AX,tempw);
 41.3764 +                        AX-=(tempw+tempc);
 41.3765 +                        cycles-=(is486)?1:2;
 41.3766 +                        break;
 41.3767 +                        case 0x11D: case 0x31D: /*SBB AX,#32*/
 41.3768 +                        templ=getlong(); if (abrt) break;
 41.3769 +                        setsbc32(EAX,templ);
 41.3770 +                        EAX-=(templ+tempc);
 41.3771 +                        cycles-=(is486)?1:2;
 41.3772 +                        break;
 41.3773 +
 41.3774 +                        case 0x1E: case 0x21E: /*PUSH DS*/
 41.3775 +                        if (ssegs) ss=oldss;
 41.3776 +                        if (stack32)
 41.3777 +                        {
 41.3778 +                                writememw(ss,ESP-2,DS);                 if (abrt) break;
 41.3779 +                                ESP-=2;
 41.3780 +                        }
 41.3781 +                        else
 41.3782 +                        {
 41.3783 +                                writememw(ss,((SP-2)&0xFFFF),DS);       if (abrt) break;
 41.3784 +                                SP-=2;
 41.3785 +                        }
 41.3786 +                        cycles-=2;
 41.3787 +                        break;
 41.3788 +                        case 0x11E: case 0x31E: /*PUSH DS*/
 41.3789 +                        if (ssegs) ss=oldss;
 41.3790 +                        if (stack32)
 41.3791 +                        {
 41.3792 +                                writememl(ss,ESP-4,DS);                 if (abrt) break;
 41.3793 +                                ESP-=4;
 41.3794 +                        }
 41.3795 +                        else
 41.3796 +                        {
 41.3797 +                                writememl(ss,((SP-4)&0xFFFF),DS);       if (abrt) break;
 41.3798 +                                SP-=4;
 41.3799 +                        }
 41.3800 +                        cycles-=2;
 41.3801 +                        break;
 41.3802 +                        case 0x1F: case 0x21F: /*POP DS*/
 41.3803 +                        if (ssegs) ss=oldss;
 41.3804 +                        if (stack32)
 41.3805 +                        {
 41.3806 +                                tempw=readmemw(ss,ESP);                 if (abrt) break;
 41.3807 +                                loadseg(tempw,&_ds); if (abrt) break;
 41.3808 +                                ESP+=2;
 41.3809 +                        }
 41.3810 +                        else
 41.3811 +                        {
 41.3812 +                                tempw=readmemw(ss,SP);                  if (abrt) break;
 41.3813 +                                loadseg(tempw,&_ds); if (abrt) break;
 41.3814 +                                SP+=2;
 41.3815 +                        }
 41.3816 +                        cycles-=(is486)?3:7;
 41.3817 +                        break;
 41.3818 +                        case 0x11F: case 0x31F: /*POP DS*/
 41.3819 +                        if (ssegs) ss=oldss;
 41.3820 +                        if (stack32)
 41.3821 +                        {
 41.3822 +                                tempw=readmemw(ss,ESP);                 if (abrt) break;
 41.3823 +                                loadseg(tempw,&_ds); if (abrt) break;
 41.3824 +                                ESP+=4;
 41.3825 +                        }
 41.3826 +                        else
 41.3827 +                        {
 41.3828 +                                tempw=readmemw(ss,SP);                  if (abrt) break;
 41.3829 +                                loadseg(tempw,&_ds); if (abrt) break;
 41.3830 +                                SP+=4;
 41.3831 +                        }
 41.3832 +                        cycles-=(is486)?3:7;
 41.3833 +                        break;
 41.3834 +
 41.3835 +                        case 0x20: case 0x120: case 0x220: case 0x320: /*AND 8,reg*/
 41.3836 +                        fetchea();
 41.3837 +                        if (mod == 3)
 41.3838 +                        {
 41.3839 +                                temp  = getr8(rm) & getr8(reg);
 41.3840 +                                setr8(rm, temp);
 41.3841 +                                setznp8(temp);
 41.3842 +                                cycles -= timing_rr;
 41.3843 +                        }
 41.3844 +                        else
 41.3845 +                        {
 41.3846 +                                temp  = geteab();    if (abrt) break;
 41.3847 +                                temp &= getr8(reg);
 41.3848 +                                seteab(temp);        if (abrt) break;
 41.3849 +                                setznp8(temp);
 41.3850 +                                cycles -= timing_mr;
 41.3851 +                        }
 41.3852 +                        break;
 41.3853 +                        case 0x21: case 0x221: /*AND 16,reg*/
 41.3854 +                        fetchea();
 41.3855 +                        if (mod == 3)
 41.3856 +                        {
 41.3857 +                                regs[rm].w &= regs[reg].w;
 41.3858 +                                setznp16(regs[rm].w);
 41.3859 +                                cycles -= timing_rr;
 41.3860 +                        }
 41.3861 +                        else
 41.3862 +                        {
 41.3863 +                                tempw = geteaw() & regs[reg].w; if (abrt) break;
 41.3864 +                                seteaw(tempw);                  if (abrt) break;
 41.3865 +                                setznp16(tempw);
 41.3866 +                                cycles -= timing_mr;
 41.3867 +                        }
 41.3868 +                        break;
 41.3869 +                        case 0x121: case 0x321: /*AND 32,reg*/
 41.3870 +                        fetchea();
 41.3871 +                        if (mod == 3)
 41.3872 +                        {
 41.3873 +                                regs[rm].l &= regs[reg].l;
 41.3874 +                                setznp32(regs[rm].l);
 41.3875 +                                cycles -= timing_rr;
 41.3876 +                        }
 41.3877 +                        else
 41.3878 +                        {
 41.3879 +                                templ = geteal() & regs[reg].l; if (abrt) break;
 41.3880 +                                seteal(templ);                  if (abrt) break;
 41.3881 +                                setznp32(templ);
 41.3882 +                                cycles -= timing_mrl;
 41.3883 +                        }
 41.3884 +                        break;
 41.3885 +                        case 0x22: case 0x122: case 0x222: case 0x322: /*AND reg,8*/
 41.3886 +                        fetchea();
 41.3887 +                        temp=geteab();          if (abrt) break;
 41.3888 +                        temp&=getr8(reg);
 41.3889 +                        setznp8(temp);
 41.3890 +                        setr8(reg,temp);
 41.3891 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3892 +                        break;
 41.3893 +                        case 0x23: case 0x223: /*AND reg,16*/
 41.3894 +                        fetchea();
 41.3895 +                        tempw=geteaw();         if (abrt) break;
 41.3896 +                        tempw&=regs[reg].w;
 41.3897 +                        setznp16(tempw);
 41.3898 +                        regs[reg].w=tempw;
 41.3899 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.3900 +                        break;
 41.3901 +                        case 0x123: case 0x323: /*AND reg,32*/
 41.3902 +                        fetchea();
 41.3903 +                        templ=geteal();         if (abrt) break;
 41.3904 +                        templ&=regs[reg].l;
 41.3905 +                        setznp32(templ);
 41.3906 +                        regs[reg].l=templ;
 41.3907 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.3908 +                        break;
 41.3909 +                        case 0x24: case 0x124: case 0x224: case 0x324: /*AND AL,#8*/
 41.3910 +                        AL&=getbytef();
 41.3911 +                        setznp8(AL);
 41.3912 +                        cycles -= timing_rr;
 41.3913 +                        break;
 41.3914 +                        case 0x25: case 0x225: /*AND AX,#16*/
 41.3915 +                        AX&=getwordf();
 41.3916 +                        setznp16(AX);
 41.3917 +                        cycles -= timing_rr;
 41.3918 +                        break;
 41.3919 +                        case 0x125: case 0x325: /*AND EAX,#32*/
 41.3920 +                        templ=getlong(); if (abrt) break;
 41.3921 +                        EAX&=templ;
 41.3922 +                        setznp32(EAX);
 41.3923 +                        cycles -= timing_rr;
 41.3924 +                        break;
 41.3925 +
 41.3926 +                        case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/
 41.3927 +                        oldss=ss;
 41.3928 +                        oldds=ds;
 41.3929 +                        ds=ss=es;
 41.3930 +                        rds=ES;
 41.3931 +                        ssegs=2;
 41.3932 +                        cycles-=4;
 41.3933 +                        goto opcodestart;
 41.3934 +//                        break;
 41.3935 +
 41.3936 +                        case 0x27: case 0x127: case 0x227: case 0x327: /*DAA*/
 41.3937 +                        if ((flags & A_FLAG) || ((AL & 0xF) > 9))
 41.3938 +                        {
 41.3939 +                                tempi = ((uint16_t)AL) + 6;
 41.3940 +                                AL += 6;
 41.3941 +                                flags |= A_FLAG;
 41.3942 +                                if (tempi & 0x100) flags |= C_FLAG;
 41.3943 +                        }
 41.3944 +//                        else
 41.3945 +//                           flags&=~A_FLAG;
 41.3946 +                        if ((flags&C_FLAG) || (AL>0x9F))
 41.3947 +                        {
 41.3948 +                                AL+=0x60;
 41.3949 +                                flags|=C_FLAG;
 41.3950 +                        }
 41.3951 +//                        else
 41.3952 +//                           flags&=~C_FLAG;
 41.3953 +                        tempw = flags & (C_FLAG | A_FLAG);
 41.3954 +                        setznp8(AL);
 41.3955 +                        flags |= tempw;
 41.3956 +                        cycles-=4;
 41.3957 +                        break;
 41.3958 +
 41.3959 +                        case 0x28: case 0x128: case 0x228: case 0x328: /*SUB 8,reg*/
 41.3960 +                        fetchea();
 41.3961 +                        if (mod == 3)
 41.3962 +                        {
 41.3963 +                                temp  = getr8(rm);
 41.3964 +                                temp2 = getr8(reg);
 41.3965 +                                setsub8(temp, temp2);
 41.3966 +                                setr8(rm, temp - temp2);
 41.3967 +                                cycles -= timing_rr;
 41.3968 +                        }
 41.3969 +                        else
 41.3970 +                        {
 41.3971 +                                temp  = geteab();     if (abrt) break;
 41.3972 +                                temp2 = getr8(reg);
 41.3973 +                                seteab(temp - temp2); if (abrt) break;
 41.3974 +                                setsub8(temp, temp2);
 41.3975 +                                cycles -= timing_mr;
 41.3976 +                        }
 41.3977 +                        break;
 41.3978 +                        case 0x29: case 0x229: /*SUB 16,reg*/
 41.3979 +                        fetchea();
 41.3980 +                        if (mod == 3)
 41.3981 +                        {
 41.3982 +                                setsub16(regs[rm].w, regs[reg].w);
 41.3983 +                                regs[rm].w -= regs[reg].w;
 41.3984 +                                cycles -= timing_rr;
 41.3985 +                        }
 41.3986 +                        else
 41.3987 +                        {
 41.3988 +                                tempw = geteaw();             if (abrt) break;
 41.3989 +                                seteaw(tempw - regs[reg].w);  if (abrt) break;
 41.3990 +                                setsub16(tempw, regs[reg].w);
 41.3991 +                                cycles -= timing_mr;
 41.3992 +                        }
 41.3993 +                        break;
 41.3994 +                        case 0x129: case 0x329: /*SUB 32,reg*/
 41.3995 +                        fetchea();
 41.3996 +                        if (mod == 3)
 41.3997 +                        {
 41.3998 +                                setsub32(regs[rm].l, regs[reg].l);
 41.3999 +                                regs[rm].l -= regs[reg].l;
 41.4000 +                                cycles -= timing_rr;
 41.4001 +                        }
 41.4002 +                        else
 41.4003 +                        {
 41.4004 +                                templ = geteal();             if (abrt) break;
 41.4005 +                                seteal(templ - regs[reg].l);  if (abrt) break;
 41.4006 +                                setsub32(templ, regs[reg].l);
 41.4007 +                                cycles -= timing_mrl;
 41.4008 +                        }
 41.4009 +                        break;
 41.4010 +                        case 0x2A: case 0x12A: case 0x22A: case 0x32A: /*SUB reg,8*/
 41.4011 +                        fetchea();
 41.4012 +                        temp=geteab();          if (abrt) break;
 41.4013 +                        setsub8(getr8(reg),temp);
 41.4014 +                        setr8(reg,getr8(reg)-temp);
 41.4015 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4016 +                        break;
 41.4017 +                        case 0x2B: case 0x22B: /*SUB reg,16*/
 41.4018 +                        fetchea();
 41.4019 +                        tempw=geteaw();         if (abrt) break;
 41.4020 +                        setsub16(regs[reg].w,tempw);
 41.4021 +                        regs[reg].w-=tempw;
 41.4022 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4023 +                        break;
 41.4024 +                        case 0x12B: case 0x32B: /*SUB reg,32*/
 41.4025 +                        fetchea();
 41.4026 +                        templ=geteal();         if (abrt) break;
 41.4027 +                        setsub32(regs[reg].l,templ);
 41.4028 +                        regs[reg].l-=templ;
 41.4029 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.4030 +                        break;
 41.4031 +                        case 0x2C: case 0x12C: case 0x22C: case 0x32C: /*SUB AL,#8*/
 41.4032 +                        temp=getbytef();
 41.4033 +                        setsub8(AL,temp);
 41.4034 +                        AL-=temp;
 41.4035 +                        cycles -= timing_rr;
 41.4036 +                        break;
 41.4037 +                        case 0x2D: case 0x22D: /*SUB AX,#16*/
 41.4038 +                        tempw=getwordf();
 41.4039 +                        setsub16(AX,tempw);
 41.4040 +                        AX-=tempw;
 41.4041 +                        cycles -= timing_rr;
 41.4042 +                        break;
 41.4043 +                        case 0x12D: case 0x32D: /*SUB EAX,#32*/
 41.4044 +                        templ=getlong(); if (abrt) break;
 41.4045 +                        setsub32(EAX,templ);
 41.4046 +                        EAX-=templ;
 41.4047 +                        cycles -= timing_rr;
 41.4048 +                        break;
 41.4049 +
 41.4050 +                        case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/
 41.4051 +                        oldss=ss;
 41.4052 +                        oldds=ds;
 41.4053 +                        ds=ss=cs;
 41.4054 +                        rds=CS;
 41.4055 +                        ssegs=2;
 41.4056 +                        cycles-=4;
 41.4057 +                        goto opcodestart;
 41.4058 +                        case 0x2F: case 0x12F: case 0x22F: case 0x32F: /*DAS*/
 41.4059 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 41.4060 +                        {
 41.4061 +                                tempi=((uint16_t)AL)-6;
 41.4062 +                                AL-=6;
 41.4063 +                                flags|=A_FLAG;
 41.4064 +                                if (tempi&0x100) flags|=C_FLAG;
 41.4065 +                        }
 41.4066 +//                        else
 41.4067 +//                           flags&=~A_FLAG;
 41.4068 +                        if ((flags&C_FLAG)||(AL>0x9F))
 41.4069 +                        {
 41.4070 +                                AL-=0x60;
 41.4071 +                                flags|=C_FLAG;
 41.4072 +                        }
 41.4073 +//                        else
 41.4074 +//                           flags&=~C_FLAG;
 41.4075 +                        tempw = flags & (C_FLAG | A_FLAG);
 41.4076 +                        setznp8(AL);
 41.4077 +                        flags |= tempw;
 41.4078 +                        cycles-=4;
 41.4079 +                        break;
 41.4080 +
 41.4081 +                        case 0x30: case 0x130: case 0x230: case 0x330: /*XOR 8,reg*/
 41.4082 +                        fetchea();
 41.4083 +                        if (mod == 3)
 41.4084 +                        {
 41.4085 +                                temp = getr8(rm) ^ getr8(reg);
 41.4086 +                                setr8(rm, temp);
 41.4087 +                                setznp8(temp);
 41.4088 +                                cycles -= timing_rr;
 41.4089 +                        }
 41.4090 +                        else
 41.4091 +                        {
 41.4092 +                                temp  = geteab();    if (abrt) break;
 41.4093 +                                temp ^= getr8(reg);
 41.4094 +                                seteab(temp);        if (abrt) break;
 41.4095 +                                setznp8(temp);
 41.4096 +                                cycles -= timing_mr;
 41.4097 +                        }
 41.4098 +                        break;
 41.4099 +                        case 0x31: case 0x231: /*XOR 16,reg*/
 41.4100 +                        fetchea();
 41.4101 +                        if (mod == 3)
 41.4102 +                        {
 41.4103 +                                regs[rm].w ^= regs[reg].w;
 41.4104 +                                setznp16(regs[rm].w);
 41.4105 +                                cycles -= timing_rr;
 41.4106 +                        }
 41.4107 +                        else
 41.4108 +                        {
 41.4109 +                                tempw = geteaw() ^ regs[reg].w; if (abrt) break;
 41.4110 +                                seteaw(tempw);                  if (abrt) break;
 41.4111 +                                setznp16(tempw);
 41.4112 +                                cycles -= timing_mr;
 41.4113 +                        }
 41.4114 +                        break;
 41.4115 +                        case 0x131: case 0x331: /*XOR 32,reg*/
 41.4116 +                        fetchea();
 41.4117 +                        if (mod == 3)
 41.4118 +                        {
 41.4119 +                                regs[rm].l ^= regs[reg].l;
 41.4120 +                                setznp32(regs[rm].l);
 41.4121 +                                cycles -= timing_rr;
 41.4122 +                        }
 41.4123 +                        else
 41.4124 +                        {
 41.4125 +                                templ = geteal() ^ regs[reg].l; if (abrt) break;
 41.4126 +                                seteal(templ);                  if (abrt) break;
 41.4127 +                                setznp32(templ);
 41.4128 +                                cycles -= timing_mrl;
 41.4129 +                        }
 41.4130 +                        break;
 41.4131 +                        case 0x32: case 0x132: case 0x232: case 0x332: /*XOR reg,8*/
 41.4132 +                        fetchea();
 41.4133 +                        temp=geteab();          if (abrt) break;
 41.4134 +                        temp^=getr8(reg);
 41.4135 +                        setznp8(temp);
 41.4136 +                        setr8(reg,temp);
 41.4137 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4138 +                        break;
 41.4139 +                        case 0x33: case 0x233: /*XOR reg,16*/
 41.4140 +                        fetchea();
 41.4141 +                        tempw=geteaw();         if (abrt) break;
 41.4142 +                        tempw^=regs[reg].w;
 41.4143 +                        setznp16(tempw);
 41.4144 +                        regs[reg].w=tempw;
 41.4145 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4146 +                        break;
 41.4147 +                        case 0x133: case 0x333: /*XOR reg,32*/
 41.4148 +                        fetchea();
 41.4149 +                        templ=geteal();         if (abrt) break;
 41.4150 +                        templ^=regs[reg].l;
 41.4151 +                        setznp32(templ);
 41.4152 +                        regs[reg].l=templ;
 41.4153 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.4154 +                        break;
 41.4155 +                        case 0x34: case 0x134: case 0x234: case 0x334: /*XOR AL,#8*/
 41.4156 +                        AL^=getbytef();
 41.4157 +                        setznp8(AL);
 41.4158 +                        cycles -= timing_rr;
 41.4159 +                        break;
 41.4160 +                        case 0x35: case 0x235: /*XOR AX,#16*/
 41.4161 +                        AX^=getwordf();
 41.4162 +                        setznp16(AX);
 41.4163 +                        cycles -= timing_rr;
 41.4164 +                        break;
 41.4165 +                        case 0x135: case 0x335: /*XOR EAX,#32*/
 41.4166 +                        templ=getlong(); if (abrt) break;
 41.4167 +                        EAX^=templ;
 41.4168 +                        setznp32(EAX);
 41.4169 +                        cycles -= timing_rr;
 41.4170 +                        break;
 41.4171 +
 41.4172 +                        case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/
 41.4173 +                        oldss=ss;
 41.4174 +                        oldds=ds;
 41.4175 +                        ds=ss=ss;
 41.4176 +                        rds=SS;
 41.4177 +                        ssegs=2;
 41.4178 +                        cycles-=4;
 41.4179 +                        goto opcodestart;
 41.4180 +//                        break;
 41.4181 +
 41.4182 +                        case 0x37: case 0x137: case 0x237: case 0x337: /*AAA*/
 41.4183 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 41.4184 +                        {
 41.4185 +                                AL+=6;
 41.4186 +                                AH++;
 41.4187 +                                flags|=(A_FLAG|C_FLAG);
 41.4188 +                        }
 41.4189 +                        else
 41.4190 +                           flags&=~(A_FLAG|C_FLAG);
 41.4191 +                        AL&=0xF;
 41.4192 +                        cycles-=(is486)?3:4;
 41.4193 +                        break;
 41.4194 +
 41.4195 +                        case 0x38: case 0x138: case 0x238: case 0x338: /*CMP 8,reg*/
 41.4196 +                        fetchea();
 41.4197 +                        temp=geteab();          if (abrt) break;
 41.4198 +                        setsub8(temp,getr8(reg));
 41.4199 +                        if (is486) cycles-=((mod==3)?1:2);
 41.4200 +                        else       cycles-=((mod==3)?2:5);
 41.4201 +                        break;
 41.4202 +                        case 0x39: case 0x239: /*CMP 16,reg*/
 41.4203 +                        fetchea();
 41.4204 +                        tempw=geteaw();         if (abrt) break;
 41.4205 +//                        if (output) pclog("CMP %04X %04X\n",tempw,regs[reg].w);
 41.4206 +                        setsub16(tempw,regs[reg].w);
 41.4207 +                        if (is486) cycles-=((mod==3)?1:2);
 41.4208 +                        else       cycles-=((mod==3)?2:5);
 41.4209 +                        break;
 41.4210 +                        case 0x139: case 0x339: /*CMP 32,reg*/
 41.4211 +                        fetchea();
 41.4212 +                        templ=geteal();         if (abrt) break;
 41.4213 +                        setsub32(templ,regs[reg].l);
 41.4214 +                        if (is486) cycles-=((mod==3)?1:2);
 41.4215 +                        else       cycles-=((mod==3)?2:5);
 41.4216 +                        break;
 41.4217 +                        case 0x3A: case 0x13A: case 0x23A: case 0x33A: /*CMP reg,8*/
 41.4218 +                        fetchea();
 41.4219 +                        temp=geteab();          if (abrt) break;
 41.4220 +//                        if (output) pclog("CMP %02X-%02X\n",getr8(reg),temp);
 41.4221 +                        setsub8(getr8(reg),temp);
 41.4222 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4223 +                        break;
 41.4224 +                        case 0x3B: case 0x23B: /*CMP reg,16*/
 41.4225 +                        fetchea();
 41.4226 +                        tempw=geteaw();         if (abrt) break;
 41.4227 +                        setsub16(regs[reg].w,tempw);
 41.4228 +                        cycles -= (mod == 3) ? timing_rr : timing_rm;
 41.4229 +                        break;
 41.4230 +                        case 0x13B: case 0x33B: /*CMP reg,32*/
 41.4231 +                        fetchea();
 41.4232 +                        templ=geteal();         if (abrt) break;
 41.4233 +                        setsub32(regs[reg].l,templ);
 41.4234 +                        cycles -= (mod == 3) ? timing_rr : timing_rml;
 41.4235 +                        break;
 41.4236 +                        case 0x3C: case 0x13C: case 0x23C: case 0x33C: /*CMP AL,#8*/
 41.4237 +                        temp=getbytef();
 41.4238 +                        setsub8(AL,temp);
 41.4239 +                        cycles -= timing_rr;
 41.4240 +                        break;
 41.4241 +                        case 0x3D: case 0x23D: /*CMP AX,#16*/
 41.4242 +                        tempw=getwordf();
 41.4243 +                        setsub16(AX,tempw);
 41.4244 +                        cycles -= timing_rr;
 41.4245 +                        break;
 41.4246 +                        case 0x13D: case 0x33D: /*CMP EAX,#32*/
 41.4247 +                        templ=getlong(); if (abrt) break;
 41.4248 +                        setsub32(EAX,templ);
 41.4249 +                        cycles -= timing_rr;
 41.4250 +                        break;
 41.4251 +
 41.4252 +                        case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/
 41.4253 +                        oldss=ss;
 41.4254 +                        oldds=ds;
 41.4255 +                        ds=ss=ds;
 41.4256 +                        ssegs=2;
 41.4257 +                        cycles-=4;
 41.4258 +                        goto opcodestart;
 41.4259 +//                        break;
 41.4260 +
 41.4261 +                        case 0x3F: case 0x13F: case 0x23F: case 0x33F: /*AAS*/
 41.4262 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
 41.4263 +                        {
 41.4264 +                                AL-=6;
 41.4265 +                                AH--;
 41.4266 +                                flags|=(A_FLAG|C_FLAG);
 41.4267 +                        }
 41.4268 +                        else
 41.4269 +                           flags&=~(A_FLAG|C_FLAG);
 41.4270 +                        AL&=0xF;
 41.4271 +                        cycles-=(is486)?3:4;
 41.4272 +                        break;
 41.4273 +
 41.4274 +                        case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
 41.4275 +                        case 0x44: case 0x45: case 0x46: case 0x47:
 41.4276 +                        case 0x240: case 0x241: case 0x242: case 0x243:
 41.4277 +                        case 0x244: case 0x245: case 0x246: case 0x247:
 41.4278 +                        setadd16nc(regs[opcode&7].w,1);
 41.4279 +                        regs[opcode&7].w++;
 41.4280 +                        cycles -= timing_rr;
 41.4281 +                        break;
 41.4282 +                        case 0x140: case 0x141: case 0x142: case 0x143: /*INC r32*/
 41.4283 +                        case 0x144: case 0x145: case 0x146: case 0x147:
 41.4284 +                        case 0x340: case 0x341: case 0x342: case 0x343:
 41.4285 +                        case 0x344: case 0x345: case 0x346: case 0x347:
 41.4286 +                        setadd32nc(regs[opcode&7].l,1);
 41.4287 +                        regs[opcode&7].l++;
 41.4288 +                        cycles -= timing_rr;
 41.4289 +                        break;
 41.4290 +                        case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/
 41.4291 +                        case 0x4C: case 0x4D: case 0x4E: case 0x4F:
 41.4292 +                        case 0x248: case 0x249: case 0x24A: case 0x24B:
 41.4293 +                        case 0x24C: case 0x24D: case 0x24E: case 0x24F:
 41.4294 +                        setsub16nc(regs[opcode&7].w,1);
 41.4295 +                        regs[opcode&7].w--;
 41.4296 +                        cycles -= timing_rr;
 41.4297 +                        break;
 41.4298 +                        case 0x148: case 0x149: case 0x14A: case 0x14B: /*DEC r32*/
 41.4299 +                        case 0x14C: case 0x14D: case 0x14E: case 0x14F:
 41.4300 +                        case 0x348: case 0x349: case 0x34A: case 0x34B:
 41.4301 +                        case 0x34C: case 0x34D: case 0x34E: case 0x34F:
 41.4302 +                        setsub32nc(regs[opcode&7].l,1);
 41.4303 +                        regs[opcode&7].l--;
 41.4304 +                        cycles -= timing_rr;
 41.4305 +                        break;
 41.4306 +
 41.4307 +                        case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
 41.4308 +                        case 0x54: case 0x55: case 0x56: case 0x57:
 41.4309 +                        case 0x250: case 0x251: case 0x252: case 0x253:
 41.4310 +                        case 0x254: case 0x255: case 0x256: case 0x257:
 41.4311 +                        if (ssegs) ss=oldss;
 41.4312 +                        if (stack32)
 41.4313 +                        {
 41.4314 +                                writememw(ss,ESP-2,regs[opcode&7].w);           if (abrt) break;
 41.4315 +                                ESP-=2;
 41.4316 +                        }
 41.4317 +                        else
 41.4318 +                        {
 41.4319 +                                writememw(ss,(SP-2)&0xFFFF,regs[opcode&7].w);   if (abrt) break;
 41.4320 +                                SP-=2;
 41.4321 +                        }
 41.4322 +//                        if (pc>=0x1A1BED && pc<0x1A1C00) pclog("PUSH %02X! %08X\n",opcode,ESP);
 41.4323 +                        cycles-=(is486)?1:2;
 41.4324 +                        break;
 41.4325 +                        case 0x150: case 0x151: case 0x152: case 0x153: /*PUSH r32*/
 41.4326 +                        case 0x154: case 0x155: case 0x156: case 0x157:
 41.4327 +                        case 0x350: case 0x351: case 0x352: case 0x353:
 41.4328 +                        case 0x354: case 0x355: case 0x356: case 0x357:
 41.4329 +                        if (ssegs) ss=oldss;
 41.4330 +                        if (stack32)
 41.4331 +                        {
 41.4332 +                                writememl(ss,ESP-4,regs[opcode&7].l);           if (abrt) break;
 41.4333 +                                ESP-=4;
 41.4334 +                        }
 41.4335 +                        else
 41.4336 +                        {
 41.4337 +                                writememl(ss,(SP-4)&0xFFFF,regs[opcode&7].l);   if (abrt) break;
 41.4338 +                                SP-=4;
 41.4339 +                        }
 41.4340 +                        cycles-=(is486)?1:2;
 41.4341 +                        break;
 41.4342 +                        case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/
 41.4343 +                        case 0x5C: case 0x5D: case 0x5E: case 0x5F:
 41.4344 +                        case 0x258: case 0x259: case 0x25A: case 0x25B:
 41.4345 +                        case 0x25C: case 0x25D: case 0x25E: case 0x25F:
 41.4346 +                        if (ssegs) ss=oldss;
 41.4347 +                        if (stack32)
 41.4348 +                        {
 41.4349 +                                ESP+=2;
 41.4350 +                                tempw=readmemw(ss,ESP-2);            if (abrt) { ESP-=2; break; }
 41.4351 +                        }
 41.4352 +                        else
 41.4353 +                        {
 41.4354 +                                SP+=2;
 41.4355 +                                tempw=readmemw(ss,(SP-2)&0xFFFF);    if (abrt) { SP-=2; break; }
 41.4356 +                        }
 41.4357 +                        regs[opcode&7].w=tempw;
 41.4358 +                        cycles-=(is486)?1:4;
 41.4359 +                        break;
 41.4360 +                        case 0x158: case 0x159: case 0x15A: case 0x15B: /*POP r32*/
 41.4361 +                        case 0x15C: case 0x15D: case 0x15E: case 0x15F:
 41.4362 +                        case 0x358: case 0x359: case 0x35A: case 0x35B:
 41.4363 +                        case 0x35C: case 0x35D: case 0x35E: case 0x35F:
 41.4364 +                        if (ssegs) ss=oldss;
 41.4365 +                        if (stack32)
 41.4366 +                        {
 41.4367 +                                ESP+=4;
 41.4368 +                                templ=readmeml(ss,ESP-4);            if (abrt) { ESP-=4; break; }
 41.4369 +                        }
 41.4370 +                        else
 41.4371 +                        {
 41.4372 +                                SP+=4;
 41.4373 +                                templ=readmeml(ss,(SP-4)&0xFFFF);    if (abrt) { SP-=4; break; }
 41.4374 +                        }
 41.4375 +                        regs[opcode&7].l=templ;
 41.4376 +                        cycles-=(is486)?1:4;
 41.4377 +                        break;
 41.4378 +
 41.4379 +                        case 0x60: case 0x260: /*PUSHA*/
 41.4380 +                        if (stack32)
 41.4381 +                        {
 41.4382 +                                writememw(ss,ESP-2,AX);
 41.4383 +                                writememw(ss,ESP-4,CX);
 41.4384 +                                writememw(ss,ESP-6,DX);
 41.4385 +                                writememw(ss,ESP-8,BX);
 41.4386 +                                writememw(ss,ESP-10,SP);
 41.4387 +                                writememw(ss,ESP-12,BP);
 41.4388 +                                writememw(ss,ESP-14,SI);
 41.4389 +                                writememw(ss,ESP-16,DI);
 41.4390 +                                if (!abrt) ESP-=16;
 41.4391 +                        }
 41.4392 +                        else
 41.4393 +                        {
 41.4394 +                                writememw(ss,((SP-2)&0xFFFF),AX);
 41.4395 +                                writememw(ss,((SP-4)&0xFFFF),CX);
 41.4396 +                                writememw(ss,((SP-6)&0xFFFF),DX);
 41.4397 +                                writememw(ss,((SP-8)&0xFFFF),BX);
 41.4398 +                                writememw(ss,((SP-10)&0xFFFF),SP);
 41.4399 +                                writememw(ss,((SP-12)&0xFFFF),BP);
 41.4400 +                                writememw(ss,((SP-14)&0xFFFF),SI);
 41.4401 +                                writememw(ss,((SP-16)&0xFFFF),DI);
 41.4402 +                                if (!abrt) SP-=16;
 41.4403 +                        }
 41.4404 +                        cycles-=(is486)?11:18;
 41.4405 +                        break;
 41.4406 +                        case 0x61: case 0x261: /*POPA*/
 41.4407 +                        if (stack32)
 41.4408 +                        {
 41.4409 +                                DI=readmemw(ss,ESP);    if (abrt) break;
 41.4410 +                                SI=readmemw(ss,ESP+2);  if (abrt) break;
 41.4411 +                                BP=readmemw(ss,ESP+4);  if (abrt) break;
 41.4412 +                                BX=readmemw(ss,ESP+8);  if (abrt) break;
 41.4413 +                                DX=readmemw(ss,ESP+10); if (abrt) break;
 41.4414 +                                CX=readmemw(ss,ESP+12); if (abrt) break;
 41.4415 +                                AX=readmemw(ss,ESP+14); if (abrt) break;
 41.4416 +                                ESP+=16;
 41.4417 +                        }
 41.4418 +                        else
 41.4419 +                        {
 41.4420 +                                DI=readmemw(ss,((SP)&0xFFFF));          if (abrt) break;
 41.4421 +                                SI=readmemw(ss,((SP+2)&0xFFFF));        if (abrt) break;
 41.4422 +                                BP=readmemw(ss,((SP+4)&0xFFFF));        if (abrt) break;
 41.4423 +                                BX=readmemw(ss,((SP+8)&0xFFFF));        if (abrt) break;
 41.4424 +                                DX=readmemw(ss,((SP+10)&0xFFFF));       if (abrt) break;
 41.4425 +                                CX=readmemw(ss,((SP+12)&0xFFFF));       if (abrt) break;
 41.4426 +                                AX=readmemw(ss,((SP+14)&0xFFFF));       if (abrt) break;
 41.4427 +                                SP+=16;
 41.4428 +                        }
 41.4429 +                        cycles-=(is486)?9:24;
 41.4430 +                        break;
 41.4431 +                        case 0x160: case 0x360: /*PUSHA*/
 41.4432 +                        if (stack32)
 41.4433 +                        {
 41.4434 +                                writememl(ss,ESP-4,EAX);
 41.4435 +                                writememl(ss,ESP-8,ECX);
 41.4436 +                                writememl(ss,ESP-12,EDX);
 41.4437 +                                writememl(ss,ESP-16,EBX);
 41.4438 +                                writememl(ss,ESP-20,ESP);
 41.4439 +                                writememl(ss,ESP-24,EBP);
 41.4440 +                                writememl(ss,ESP-28,ESI);
 41.4441 +                                writememl(ss,ESP-32,EDI);
 41.4442 +                                if (!abrt) ESP-=32;
 41.4443 +                        }
 41.4444 +                        else
 41.4445 +                        {
 41.4446 +                                writememl(ss,((SP-4)&0xFFFF),EAX);
 41.4447 +                                writememl(ss,((SP-8)&0xFFFF),ECX);
 41.4448 +                                writememl(ss,((SP-12)&0xFFFF),EDX);
 41.4449 +                                writememl(ss,((SP-16)&0xFFFF),EBX);
 41.4450 +                                writememl(ss,((SP-20)&0xFFFF),ESP);
 41.4451 +                                writememl(ss,((SP-24)&0xFFFF),EBP);
 41.4452 +                                writememl(ss,((SP-28)&0xFFFF),ESI);
 41.4453 +                                writememl(ss,((SP-32)&0xFFFF),EDI);
 41.4454 +                                if (!abrt) SP-=32;
 41.4455 +                        }
 41.4456 +                        cycles-=(is486)?11:18;
 41.4457 +                        break;
 41.4458 +                        case 0x161: case 0x361: /*POPA*/
 41.4459 +                        if (stack32)
 41.4460 +                        {
 41.4461 +                                EDI=readmeml(ss,ESP);           if (abrt) break;
 41.4462 +                                ESI=readmeml(ss,ESP+4);         if (abrt) break;
 41.4463 +                                EBP=readmeml(ss,ESP+8);         if (abrt) break;
 41.4464 +                                EBX=readmeml(ss,ESP+16);        if (abrt) break;
 41.4465 +                                EDX=readmeml(ss,ESP+20);        if (abrt) break;
 41.4466 +                                ECX=readmeml(ss,ESP+24);        if (abrt) break;
 41.4467 +                                EAX=readmeml(ss,ESP+28);        if (abrt) break;
 41.4468 +                                ESP+=32;
 41.4469 +                        }
 41.4470 +                        else
 41.4471 +                        {
 41.4472 +                                EDI=readmeml(ss,((SP)&0xFFFF));         if (abrt) break;
 41.4473 +                                ESI=readmeml(ss,((SP+4)&0xFFFF));       if (abrt) break;
 41.4474 +                                EBP=readmeml(ss,((SP+8)&0xFFFF));       if (abrt) break;
 41.4475 +                                EBX=readmeml(ss,((SP+16)&0xFFFF));      if (abrt) break;
 41.4476 +                                EDX=readmeml(ss,((SP+20)&0xFFFF));      if (abrt) break;
 41.4477 +                                ECX=readmeml(ss,((SP+24)&0xFFFF));      if (abrt) break;
 41.4478 +                                EAX=readmeml(ss,((SP+28)&0xFFFF));      if (abrt) break;
 41.4479 +                                SP+=32;
 41.4480 +                        }
 41.4481 +                        cycles-=(is486)?9:24;
 41.4482 +                        break;
 41.4483 +
 41.4484 +                        case 0x62: case 0x262: /*BOUND*/
 41.4485 +                        fetchea();
 41.4486 +                        tempw=geteaw();
 41.4487 +                        tempw2=readmemw(easeg,eaaddr+2); if (abrt) break;
 41.4488 +                        if (((int16_t)regs[reg].w<(int16_t)tempw) || ((int16_t)regs[reg].w>(int16_t)tempw2))
 41.4489 +                        {
 41.4490 +                                x86_int(5);
 41.4491 +                        }
 41.4492 +                        cycles-=(is486)?7:10;
 41.4493 +                        break;
 41.4494 +                        case 0x162: case 0x362: /*BOUND*/
 41.4495 +                        fetchea();
 41.4496 +                        templ=geteal();
 41.4497 +                        templ2=readmeml(easeg,eaaddr+4); if (abrt) break;
 41.4498 +                        if (((int32_t)regs[reg].l<(int32_t)templ) || ((int32_t)regs[reg].l>(int32_t)templ2))
 41.4499 +                        {
 41.4500 +                                x86_int(5);
 41.4501 +                        }
 41.4502 +                        cycles-=(is486)?7:10;
 41.4503 +                        break;
 41.4504 +
 41.4505 +                        
 41.4506 +                        case 0x63: case 0x163: case 0x263: case 0x363: /*ARPL*/
 41.4507 +                        NOTRM
 41.4508 +                        fetchea();
 41.4509 +                        tempw=geteaw(); if (abrt) break;
 41.4510 +                        if ((tempw&3)<(regs[reg].w&3))
 41.4511 +                        {
 41.4512 +                                tempw=(tempw&0xFFFC)|(regs[reg].w&3);
 41.4513 +                                seteaw(tempw); if (abrt) break;
 41.4514 +                                flags|=Z_FLAG;
 41.4515 +                        }
 41.4516 +                        else
 41.4517 +                           flags&=~Z_FLAG;
 41.4518 +                        cycles-=(is486)?9:20;
 41.4519 +                        break;
 41.4520 +                        case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/
 41.4521 +                        oldss=ss;
 41.4522 +                        oldds=ds;
 41.4523 +                        rds=FS;
 41.4524 +                        ds=ss=fs;
 41.4525 +                        ssegs=2;
 41.4526 +                        cycles-=4;
 41.4527 +                        goto opcodestart;
 41.4528 +                        case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/
 41.4529 +                        oldss=ss;
 41.4530 +                        oldds=ds;
 41.4531 +                        rds=GS;
 41.4532 +                        ds=ss=gs;
 41.4533 +                        ssegs=2;
 41.4534 +                        cycles-=4;
 41.4535 +                        goto opcodestart;
 41.4536 +
 41.4537 +                        case 0x66: case 0x166: case 0x266: case 0x366: /*Data size select*/
 41.4538 +                        op32=((use32&0x100)^0x100)|(op32&0x200);
 41.4539 +//                        op32^=0x100;
 41.4540 +                        cycles-=2;
 41.4541 +                        goto opcodestart;
 41.4542 +                        case 0x67: case 0x167: case 0x267: case 0x367: /*Address size select*/
 41.4543 +                        op32=((use32&0x200)^0x200)|(op32&0x100);
 41.4544 +//                        op32^=0x200;
 41.4545 +                        cycles-=2;
 41.4546 +                        goto opcodestart;
 41.4547 +
 41.4548 +                        case 0x68: case 0x268: /*PUSH #w*/
 41.4549 +                        tempw=getword();
 41.4550 +                        if (stack32)
 41.4551 +                        {
 41.4552 +                                writememw(ss,ESP-2,tempw);              if (abrt) break;
 41.4553 +                                ESP-=2;
 41.4554 +                        }
 41.4555 +                        else
 41.4556 +                        {
 41.4557 +                                writememw(ss,((SP-2)&0xFFFF),tempw);    if (abrt) break;
 41.4558 +                                SP-=2;
 41.4559 +                        }
 41.4560 +                        cycles-=2;
 41.4561 +                        break;
 41.4562 +                        case 0x168: case 0x368: /*PUSH #l*/
 41.4563 +                        templ=getlong();
 41.4564 +                        if (stack32)
 41.4565 +                        {
 41.4566 +                                writememl(ss,ESP-4,templ);              if (abrt) break;
 41.4567 +                                ESP-=4;
 41.4568 +                        }
 41.4569 +                        else
 41.4570 +                        {
 41.4571 +                                writememl(ss,((SP-4)&0xFFFF),templ);    if (abrt) break;
 41.4572 +                                SP-=4;
 41.4573 +                        }
 41.4574 +                        cycles-=2;
 41.4575 +                        break;
 41.4576 +                        case 0x69: case 0x269: /*IMUL r16*/
 41.4577 +                        fetchea();
 41.4578 +                        tempw=geteaw();         if (abrt) break;
 41.4579 +                        tempw2=getword();       if (abrt) break;
 41.4580 +                        templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2);
 41.4581 +                        if ((templ>>16)!=0 && (templ>>16)!=0xFFFF) flags|=C_FLAG|V_FLAG;
 41.4582 +                        else                                       flags&=~(C_FLAG|V_FLAG);
 41.4583 +                        regs[reg].w=templ&0xFFFF;
 41.4584 +                        cycles-=((mod==3)?14:17);
 41.4585 +                        break;
 41.4586 +                        case 0x169: case 0x369: /*IMUL r32*/
 41.4587 +                        fetchea();
 41.4588 +                        templ=geteal();         if (abrt) break;
 41.4589 +                        templ2=getlong();       if (abrt) break;
 41.4590 +                        temp64=((int64_t)(int32_t)templ)*((int64_t)(int32_t)templ2);
 41.4591 +                        if ((temp64>>32)!=0 && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG;
 41.4592 +                        else                                             flags&=~(C_FLAG|V_FLAG);
 41.4593 +                        regs[reg].l=temp64&0xFFFFFFFF;
 41.4594 +                        cycles-=25;
 41.4595 +                        break;
 41.4596 +                        case 0x6A: case 0x26A:/*PUSH #eb*/
 41.4597 +                        tempw=readmemb(cs,pc); pc++;
 41.4598 +                        if (tempw&0x80) tempw|=0xFF00;
 41.4599 +                        if (output) pclog("PUSH %04X %i\n",tempw,stack32);
 41.4600 +                        if (stack32)
 41.4601 +                        {
 41.4602 +                                writememw(ss,ESP-2,tempw);              if (abrt) break;
 41.4603 +                                ESP-=2;
 41.4604 +                        }
 41.4605 +                        else
 41.4606 +                        {
 41.4607 +                                writememw(ss,((SP-2)&0xFFFF),tempw);    if (abrt) break;
 41.4608 +                                SP-=2;
 41.4609 +                        }
 41.4610 +                        cycles-=2;
 41.4611 +                        break;
 41.4612 +                        case 0x16A: case 0x36A:/*PUSH #eb*/
 41.4613 +                        templ=readmemb(cs,pc); pc++;
 41.4614 +                        if (templ&0x80) templ|=0xFFFFFF00;
 41.4615 +                        if (output) pclog("PUSH %08X %i\n",templ,stack32);
 41.4616 +                        if (stack32)
 41.4617 +                        {
 41.4618 +                                writememl(ss,ESP-4,templ);              if (abrt) break;
 41.4619 +                                ESP-=4;
 41.4620 +                        }
 41.4621 +                        else
 41.4622 +                        {
 41.4623 +                                writememl(ss,((SP-4)&0xFFFF),templ);    if (abrt) break;
 41.4624 +                                SP-=4;
 41.4625 +                        }
 41.4626 +                        cycles-=2;
 41.4627 +                        break;
 41.4628 +//                        #if 0
 41.4629 +                        case 0x6B: case 0x26B: /*IMUL r8*/
 41.4630 +                        fetchea();
 41.4631 +                        tempw=geteaw();                 if (abrt) break;
 41.4632 +                        tempw2=readmemb(cs,pc); pc++;   if (abrt) break;
 41.4633 +                        if (tempw2&0x80) tempw2|=0xFF00;
 41.4634 +                        templ=((int)(int16_t)tempw)*((int)(int16_t)tempw2);
 41.4635 +//                        pclog("IMULr8  %08X %08X %08X\n",tempw,tempw2,templ);
 41.4636 +                        if ((templ>>16)!=0 && ((templ>>16)&0xFFFF)!=0xFFFF) flags|=C_FLAG|V_FLAG;
 41.4637 +                        else                                                flags&=~(C_FLAG|V_FLAG);
 41.4638 +                        regs[reg].w=templ&0xFFFF;
 41.4639 +                        cycles-=((mod==3)?14:17);
 41.4640 +                        break;
 41.4641 +                        case 0x16B: case 0x36B: /*IMUL r8*/
 41.4642 +                        fetchea();
 41.4643 +                        templ=geteal();                 if (abrt) break;
 41.4644 +                        templ2=readmemb(cs,pc); pc++;   if (abrt) break;
 41.4645 +                        if (templ2&0x80) templ2|=0xFFFFFF00;
 41.4646 +                        temp64=((int64_t)(int32_t)templ)*((int64_t)(int32_t)templ2);
 41.4647 +//                        pclog("IMULr8  %08X %08X %i\n",templ,templ2,temp64i>>32);
 41.4648 +                        if ((temp64>>32)!=0 && (temp64>>32)!=0xFFFFFFFF) flags|=C_FLAG|V_FLAG;
 41.4649 +                        else                                             flags&=~(C_FLAG|V_FLAG);
 41.4650 +                        regs[reg].l=temp64&0xFFFFFFFF;
 41.4651 +                        cycles-=20;
 41.4652 +                        break;
 41.4653 +//#endif
 41.4654 +                        case 0x6C: case 0x16C: /*INSB*/
 41.4655 +                        checkio_perm(DX);
 41.4656 +                        temp=inb(DX);
 41.4657 +                        writememb(es,DI,temp);          if (abrt) break;
 41.4658 +                        if (flags&D_FLAG) DI--;
 41.4659 +                        else              DI++;
 41.4660 +                        cycles-=15;
 41.4661 +                        break;
 41.4662 +                        case 0x26C: case 0x36C: /*INSB*/
 41.4663 +                        checkio_perm(DX);
 41.4664 +                        temp=inb(DX);
 41.4665 +                        writememb(es,EDI,temp);         if (abrt) break;
 41.4666 +                        if (flags&D_FLAG) EDI--;
 41.4667 +                        else              EDI++;
 41.4668 +                        cycles-=15;
 41.4669 +                        break;
 41.4670 +                        case 0x6D: /*INSW*/
 41.4671 +                        checkio_perm(DX);
 41.4672 +                        checkio_perm(DX+1);
 41.4673 +                        tempw=inw(DX);
 41.4674 +                        writememw(es,DI,tempw);         if (abrt) break;
 41.4675 +                        if (flags&D_FLAG) DI-=2;
 41.4676 +                        else              DI+=2;
 41.4677 +                        cycles-=15;
 41.4678 +                        break;
 41.4679 +                        case 0x16D: /*INSL*/
 41.4680 +                        checkio_perm(DX);
 41.4681 +                        checkio_perm(DX+1);
 41.4682 +                        checkio_perm(DX+2);
 41.4683 +                        checkio_perm(DX+3);
 41.4684 +                        templ=inl(DX);
 41.4685 +                        writememl(es,DI,templ);         if (abrt) break;
 41.4686 +                        if (flags&D_FLAG) DI-=4;
 41.4687 +                        else              DI+=4;
 41.4688 +                        cycles-=15;
 41.4689 +                        break;
 41.4690 +                        case 0x26D: /*INSW*/
 41.4691 +                        checkio_perm(DX);
 41.4692 +                        checkio_perm(DX+1);
 41.4693 +                        tempw=inw(DX);
 41.4694 +                        writememw(es,EDI,tempw);         if (abrt) break;
 41.4695 +                        if (flags&D_FLAG) EDI-=2;
 41.4696 +                        else              EDI+=2;
 41.4697 +                        cycles-=15;
 41.4698 +                        break;
 41.4699 +                        case 0x36D: /*INSL*/
 41.4700 +                        checkio_perm(DX);
 41.4701 +                        checkio_perm(DX+1);
 41.4702 +                        checkio_perm(DX+2);
 41.4703 +                        checkio_perm(DX+3);
 41.4704 +                        templ=inl(DX);
 41.4705 +                        writememl(es,EDI,templ);         if (abrt) break;
 41.4706 +                        if (flags&D_FLAG) EDI-=4;
 41.4707 +                        else              EDI+=4;
 41.4708 +                        cycles-=15;
 41.4709 +                        break;
 41.4710 +                        case 0x6E: case 0x16E: /*OUTSB*/
 41.4711 +                        temp=readmemb(ds,SI);           if (abrt) break;
 41.4712 +                        checkio_perm(DX);
 41.4713 +                        if (flags&D_FLAG) SI--;
 41.4714 +                        else              SI++;
 41.4715 +                        outb(DX,temp);
 41.4716 +                        cycles-=14;
 41.4717 +                        break;
 41.4718 +                        case 0x26E: case 0x36E: /*OUTSB*/
 41.4719 +                        checkio_perm(DX);
 41.4720 +                        temp=readmemb(ds,ESI);          if (abrt) break;
 41.4721 +                        if (flags&D_FLAG) ESI--;
 41.4722 +                        else              ESI++;
 41.4723 +                        outb(DX,temp);
 41.4724 +                        cycles-=14;
 41.4725 +                        break;
 41.4726 +                        case 0x6F: /*OUTSW*/
 41.4727 +                        tempw=readmemw(ds,SI);          if (abrt) break;
 41.4728 +                        checkio_perm(DX);
 41.4729 +                        checkio_perm(DX+1);
 41.4730 +                        if (flags&D_FLAG) SI-=2;
 41.4731 +                        else              SI+=2;
 41.4732 +                        outw(DX,tempw);
 41.4733 +//                        outb(DX+1,tempw>>8);
 41.4734 +                        cycles-=14;
 41.4735 +                        break;
 41.4736 +                        case 0x16F: /*OUTSL*/
 41.4737 +                        tempw=readmemw(ds,SI);         if (abrt) break;
 41.4738 +                        checkio_perm(DX);
 41.4739 +                        checkio_perm(DX+1);
 41.4740 +                        checkio_perm(DX+2);
 41.4741 +                        checkio_perm(DX+3);
 41.4742 +                        if (flags&D_FLAG) SI-=4;
 41.4743 +                        else              SI+=4;
 41.4744 +                        outl(EDX,templ);
 41.4745 +                        cycles-=14;
 41.4746 +                        break;
 41.4747 +                        case 0x26F: /*OUTSW*/
 41.4748 +                        tempw=readmemw(ds,ESI);         if (abrt) break;
 41.4749 +                        checkio_perm(DX);
 41.4750 +                        checkio_perm(DX+1);
 41.4751 +                        if (flags&D_FLAG) ESI-=2;
 41.4752 +                        else              ESI+=2;
 41.4753 +                        outw(DX,tempw);
 41.4754 +                        cycles-=14;
 41.4755 +                        break;
 41.4756 +                        case 0x36F: /*OUTSL*/
 41.4757 +                        tempw=readmemw(ds,ESI);         if (abrt) break;
 41.4758 +                        checkio_perm(DX);
 41.4759 +                        checkio_perm(DX+1);
 41.4760 +                        checkio_perm(DX+2);
 41.4761 +                        checkio_perm(DX+3);
 41.4762 +                        if (flags&D_FLAG) ESI-=4;
 41.4763 +                        else              ESI+=4;
 41.4764 +                        outl(EDX,templ);
 41.4765 +                        cycles-=14;
 41.4766 +                        break;
 41.4767 +
 41.4768 +                        case 0x70: case 0x170: case 0x270: case 0x370: /*JO*/
 41.4769 +                        offset=(int8_t)getbytef();
 41.4770 +                        if (flags&V_FLAG) { pc += offset; cycles -= timing_bt; }
 41.4771 +                        cycles -= timing_bnt;
 41.4772 +                        break;
 41.4773 +                        case 0x71: case 0x171: case 0x271: case 0x371: /*JNO*/
 41.4774 +                        offset=(int8_t)getbytef();
 41.4775 +                        if (!(flags&V_FLAG)) { pc += offset; cycles -= timing_bt; }
 41.4776 +                        cycles -= timing_bnt;
 41.4777 +                        break;
 41.4778 +                        case 0x72: case 0x172: case 0x272: case 0x372: /*JB*/
 41.4779 +                        offset=(int8_t)getbytef();
 41.4780 +                        if (flags&C_FLAG) { pc += offset; cycles -= timing_bt; }
 41.4781 +                        cycles -= timing_bnt;
 41.4782 +                        break;
 41.4783 +                        case 0x73: case 0x173: case 0x273: case 0x373: /*JNB*/
 41.4784 +                        offset=(int8_t)getbytef();
 41.4785 +                        if (!(flags&C_FLAG)) { pc += offset; cycles -= timing_bt; }
 41.4786 +                        cycles -= timing_bnt;
 41.4787 +                        break;
 41.4788 +                        case 0x74: case 0x174: case 0x274: case 0x374: /*JZ*/
 41.4789 +                        offset=(int8_t)getbytef();
 41.4790 +                        if (flags&Z_FLAG) { pc += offset; cycles -= timing_bt; }
 41.4791 +                        cycles -= timing_bnt;
 41.4792 +                        break;
 41.4793 +                        case 0x75: case 0x175: case 0x275: case 0x375: /*JNZ*/
 41.4794 +                        offset=(int8_t)getbytef();
 41.4795 +                        if (!(flags&Z_FLAG)) { pc += offset; cycles -= timing_bt; }
 41.4796 +                        cycles -= timing_bnt;
 41.4797 +                        break;
 41.4798 +                        case 0x76: case 0x176: case 0x276: case 0x376: /*JBE*/
 41.4799 +                        offset=(int8_t)getbytef();
 41.4800 +                        if (flags&(C_FLAG|Z_FLAG)) { pc += offset; cycles -= timing_bt; }
 41.4801 +                        cycles -= timing_bnt;
 41.4802 +                        break;
 41.4803 +                        case 0x77: case 0x177: case 0x277: case 0x377: /*JNBE*/
 41.4804 +                        offset=(int8_t)getbytef();
 41.4805 +                        if (!(flags&(C_FLAG|Z_FLAG))) { pc += offset; cycles -= timing_bt; }
 41.4806 +                        cycles -= timing_bnt;
 41.4807 +                        break;
 41.4808 +                        case 0x78: case 0x178: case 0x278: case 0x378: /*JS*/
 41.4809 +                        offset=(int8_t)getbytef();
 41.4810 +                        if (flags&N_FLAG)  { pc += offset; cycles -= timing_bt; }
 41.4811 +                        cycles -= timing_bnt;
 41.4812 +                        break;
 41.4813 +                        case 0x79: case 0x179: case 0x279: case 0x379: /*JNS*/
 41.4814 +                        offset=(int8_t)getbytef();
 41.4815 +                        if (!(flags&N_FLAG))  { pc += offset; cycles -= timing_bt; }
 41.4816 +                        cycles -= timing_bnt;
 41.4817 +                        break;
 41.4818 +                        case 0x7A: case 0x17A: case 0x27A: case 0x37A: /*JP*/
 41.4819 +                        offset=(int8_t)getbytef();
 41.4820 +                        if (flags&P_FLAG)  { pc += offset; cycles -= timing_bt; }
 41.4821 +                        cycles -= timing_bnt;
 41.4822 +                        break;
 41.4823 +                        case 0x7B: case 0x17B: case 0x27B: case 0x37B: /*JNP*/
 41.4824 +                        offset=(int8_t)getbytef();
 41.4825 +                        if (!(flags&P_FLAG))  { pc += offset; cycles -= timing_bt; }
 41.4826 +                        cycles -= timing_bnt;
 41.4827 +                        break;
 41.4828 +                        case 0x7C: case 0x17C: case 0x27C: case 0x37C: /*JL*/
 41.4829 +                        offset=(int8_t)getbytef();
 41.4830 +                        temp=(flags&N_FLAG)?1:0;
 41.4831 +                        temp2=(flags&V_FLAG)?1:0;
 41.4832 +                        if (temp!=temp2)  { pc += offset; cycles -= timing_bt; }
 41.4833 +                        cycles -= timing_bnt;
 41.4834 +                        break;
 41.4835 +                        case 0x7D: case 0x17D: case 0x27D: case 0x37D: /*JNL*/
 41.4836 +                        offset=(int8_t)getbytef();
 41.4837 +                        temp=(flags&N_FLAG)?1:0;
 41.4838 +                        temp2=(flags&V_FLAG)?1:0;
 41.4839 +                        if (temp==temp2)  { pc += offset; cycles -= timing_bt; }
 41.4840 +                        cycles -= timing_bnt;
 41.4841 +                        break;
 41.4842 +                        case 0x7E: case 0x17E: case 0x27E: case 0x37E: /*JLE*/
 41.4843 +                        offset=(int8_t)getbytef();
 41.4844 +                        temp=(flags&N_FLAG)?1:0;
 41.4845 +                        temp2=(flags&V_FLAG)?1:0;
 41.4846 +                        if ((flags&Z_FLAG) || (temp!=temp2))  { pc += offset; cycles -= timing_bt; }
 41.4847 +                        cycles -= timing_bnt;
 41.4848 +                        break;
 41.4849 +                        case 0x7F: case 0x17F: case 0x27F: case 0x37F: /*JNLE*/
 41.4850 +                        offset=(int8_t)getbytef();
 41.4851 +                        temp=(flags&N_FLAG)?1:0;
 41.4852 +                        temp2=(flags&V_FLAG)?1:0;
 41.4853 +                        if (!((flags&Z_FLAG) || (temp!=temp2)))  { pc += offset; cycles -= timing_bt; }
 41.4854 +                        cycles -= timing_bnt;
 41.4855 +                        break;
 41.4856 +
 41.4857 +
 41.4858 +                        case 0x80: case 0x180: case 0x280: case 0x380:
 41.4859 +                        case 0x82: case 0x182: case 0x282: case 0x382:
 41.4860 +                        fetchea();
 41.4861 +                        temp=geteab();                  if (abrt) break;
 41.4862 +                        temp2=readmemb(cs,pc); pc++;    if (abrt) break;
 41.4863 +                        switch (rmdat&0x38)
 41.4864 +                        {
 41.4865 +                                case 0x00: /*ADD b,#8*/
 41.4866 +                                seteab(temp+temp2);             if (abrt) break;
 41.4867 +                                setadd8(temp,temp2);
 41.4868 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4869 +                                break;
 41.4870 +                                case 0x08: /*OR b,#8*/
 41.4871 +                                temp|=temp2;
 41.4872 +                                seteab(temp);                   if (abrt) break;
 41.4873 +                                setznp8(temp);
 41.4874 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4875 +                                break;
 41.4876 +                                case 0x10: /*ADC b,#8*/
 41.4877 +                                seteab(temp+temp2+tempc);       if (abrt) break;
 41.4878 +                                setadc8(temp,temp2);
 41.4879 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4880 +                                break;
 41.4881 +                                case 0x18: /*SBB b,#8*/
 41.4882 +                                seteab(temp-(temp2+tempc));     if (abrt) break;
 41.4883 +                                setsbc8(temp,temp2);
 41.4884 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4885 +                                break;
 41.4886 +                                case 0x20: /*AND b,#8*/
 41.4887 +                                temp&=temp2;
 41.4888 +                                seteab(temp);                   if (abrt) break;
 41.4889 +                                setznp8(temp);
 41.4890 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4891 +                                break;
 41.4892 +                                case 0x28: /*SUB b,#8*/
 41.4893 +                                seteab(temp-temp2);             if (abrt) break;
 41.4894 +                                setsub8(temp,temp2);
 41.4895 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4896 +                                break;
 41.4897 +                                case 0x30: /*XOR b,#8*/
 41.4898 +                                temp^=temp2;
 41.4899 +                                seteab(temp);                   if (abrt) break;
 41.4900 +                                setznp8(temp);
 41.4901 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4902 +                                break;
 41.4903 +                                case 0x38: /*CMP b,#8*/
 41.4904 +                                setsub8(temp,temp2);
 41.4905 +                                if (is486) cycles-=((mod==3)?1:2);
 41.4906 +                                else       cycles-=((mod==3)?2:7);
 41.4907 +                                break;
 41.4908 +                        }
 41.4909 +                        break;
 41.4910 +
 41.4911 +                        case 0x81: case 0x281:
 41.4912 +                        fetchea();
 41.4913 +                        tempw=geteaw();         if (abrt) break;
 41.4914 +                        tempw2=getword();       if (abrt) break;
 41.4915 +                        switch (rmdat&0x38)
 41.4916 +                        {
 41.4917 +                                case 0x00: /*ADD w,#16*/
 41.4918 +                                seteaw(tempw+tempw2);   if (abrt) break;
 41.4919 +                                setadd16(tempw,tempw2);
 41.4920 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4921 +                                break;
 41.4922 +                                case 0x08: /*OR w,#16*/
 41.4923 +                                tempw|=tempw2;
 41.4924 +                                seteaw(tempw);          if (abrt) break;
 41.4925 +                                setznp16(tempw);
 41.4926 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4927 +                                break;
 41.4928 +                                case 0x10: /*ADC w,#16*/
 41.4929 +                                seteaw(tempw+tempw2+tempc); if (abrt) break;
 41.4930 +                                setadc16(tempw,tempw2);
 41.4931 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4932 +                                break;
 41.4933 +                                case 0x20: /*AND w,#16*/
 41.4934 +                                tempw&=tempw2;
 41.4935 +                                seteaw(tempw);          if (abrt) break;
 41.4936 +                                setznp16(tempw);
 41.4937 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4938 +                                break;
 41.4939 +                                case 0x18: /*SBB w,#16*/
 41.4940 +                                seteaw(tempw-(tempw2+tempc));   if (abrt) break;
 41.4941 +                                setsbc16(tempw,tempw2);
 41.4942 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4943 +                                break;
 41.4944 +                                case 0x28: /*SUB w,#16*/
 41.4945 +                                seteaw(tempw-tempw2);           if (abrt) break;
 41.4946 +                                setsub16(tempw,tempw2);
 41.4947 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4948 +                                break;
 41.4949 +                                case 0x30: /*XOR w,#16*/
 41.4950 +                                tempw^=tempw2;
 41.4951 +                                seteaw(tempw);                  if (abrt) break;
 41.4952 +                                setznp16(tempw);
 41.4953 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.4954 +                                break;
 41.4955 +                                case 0x38: /*CMP w,#16*/
 41.4956 +                                setsub16(tempw,tempw2);
 41.4957 +                                if (is486) cycles-=((mod==3)?1:2);
 41.4958 +                                else       cycles-=((mod==3)?2:7);
 41.4959 +                                break;
 41.4960 +                        }
 41.4961 +                        break;
 41.4962 +                        case 0x181: case 0x381:
 41.4963 +                        fetchea();
 41.4964 +                        templ=geteal();         if (abrt) break;
 41.4965 +                        templ2=getlong();       if (abrt) break;
 41.4966 +                        switch (rmdat&0x38)
 41.4967 +                        {
 41.4968 +                                case 0x00: /*ADD l,#32*/
 41.4969 +                                seteal(templ+templ2);           if (abrt) break;
 41.4970 +                                setadd32(templ,templ2);
 41.4971 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4972 +                                break;
 41.4973 +                                case 0x08: /*OR l,#32*/
 41.4974 +                                templ|=templ2;
 41.4975 +                                seteal(templ);                  if (abrt) break;
 41.4976 +                                setznp32(templ);
 41.4977 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4978 +                                break;
 41.4979 +                                case 0x10: /*ADC l,#32*/
 41.4980 +                                seteal(templ+templ2+tempc);     if (abrt) break;
 41.4981 +                                setadc32(templ,templ2);
 41.4982 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4983 +                                break;
 41.4984 +                                case 0x20: /*AND l,#32*/
 41.4985 +                                templ&=templ2;
 41.4986 +                                seteal(templ);                  if (abrt) break;
 41.4987 +                                setznp32(templ);
 41.4988 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4989 +                                break;
 41.4990 +                                case 0x18: /*SBB l,#32*/
 41.4991 +                                seteal(templ-(templ2+tempc));   if (abrt) break;
 41.4992 +                                setsbc32(templ,templ2);
 41.4993 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4994 +                                break;
 41.4995 +                                case 0x28: /*SUB l,#32*/
 41.4996 +                                seteal(templ-templ2);           if (abrt) break;
 41.4997 +                                setsub32(templ,templ2);
 41.4998 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.4999 +                                break;
 41.5000 +                                case 0x30: /*XOR l,#32*/
 41.5001 +                                templ^=templ2;
 41.5002 +                                seteal(templ);                  if (abrt) break;
 41.5003 +                                setznp32(templ);
 41.5004 +                                cycles -= (mod == 3) ? timing_rr : timing_mrl;
 41.5005 +                                break;
 41.5006 +                                case 0x38: /*CMP l,#32*/
 41.5007 +                                setsub32(templ,templ2);
 41.5008 +                                if (is486) cycles-=((mod==3)?1:2);
 41.5009 +                                else       cycles-=((mod==3)?2:7);
 41.5010 +                                break;
 41.5011 +                        }
 41.5012 +                        break;
 41.5013 +
 41.5014 +                        case 0x83: case 0x283:
 41.5015 +                        fetchea();
 41.5016 +                        tempw=geteaw();                 if (abrt) break;
 41.5017 +                        tempw2=readmemb(cs,pc); pc++;   if (abrt) break;
 41.5018 +                        if (tempw2&0x80) tempw2|=0xFF00;
 41.5019 +                        switch (rmdat&0x38)
 41.5020 +                        {
 41.5021 +                                case 0x00: /*ADD w,#8*/
 41.5022 +                                seteaw(tempw+tempw2);           if (abrt) break;
 41.5023 +                                setadd16(tempw,tempw2);
 41.5024 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5025 +                                break;
 41.5026 +                                case 0x08: /*OR w,#8*/
 41.5027 +                                tempw|=tempw2;
 41.5028 +                                seteaw(tempw);                  if (abrt) break;
 41.5029 +                                setznp16(tempw);
 41.5030 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5031 +                                break;
 41.5032 +                                case 0x10: /*ADC w,#8*/
 41.5033 +                                seteaw(tempw+tempw2+tempc);     if (abrt) break;
 41.5034 +                                setadc16(tempw,tempw2);
 41.5035 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5036 +                                break;
 41.5037 +                                case 0x18: /*SBB w,#8*/
 41.5038 +                                seteaw(tempw-(tempw2+tempc));   if (abrt) break;
 41.5039 +                                setsbc16(tempw,tempw2);
 41.5040 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5041 +                                break;
 41.5042 +                                case 0x20: /*AND w,#8*/
 41.5043 +                                tempw&=tempw2;
 41.5044 +                                seteaw(tempw);                  if (abrt) break;
 41.5045 +                                setznp16(tempw);
 41.5046 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5047 +                                break;
 41.5048 +                                case 0x28: /*SUB w,#8*/
 41.5049 +                                seteaw(tempw-tempw2);           if (abrt) break;
 41.5050 +                                setsub16(tempw,tempw2);
 41.5051 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5052 +                                break;
 41.5053 +                                case 0x30: /*XOR w,#8*/
 41.5054 +                                tempw^=tempw2;
 41.5055 +                                seteaw(tempw);                  if (abrt) break;
 41.5056 +                                setznp16(tempw);
 41.5057 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5058 +                                break;
 41.5059 +                                case 0x38: /*CMP w,#8*/
 41.5060 +                                setsub16(tempw,tempw2);
 41.5061 +                                if (is486) cycles-=((mod==3)?1:2);
 41.5062 +                                else       cycles-=((mod==3)?2:7);
 41.5063 +                                break;
 41.5064 +                        }
 41.5065 +                        break;
 41.5066 +                        case 0x183: case 0x383:
 41.5067 +                        fetchea();
 41.5068 +                        templ=geteal();                 if (abrt) break;
 41.5069 +                        templ2=readmemb(cs,pc); pc++;   if (abrt) break;
 41.5070 +                        if (templ2&0x80) templ2|=0xFFFFFF00;
 41.5071 +                        switch (rmdat&0x38)
 41.5072 +                        {
 41.5073 +                                case 0x00: /*ADD l,#32*/
 41.5074 +                                seteal(templ+templ2);           if (abrt) break;
 41.5075 +                                setadd32(templ,templ2);
 41.5076 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5077 +                                break;
 41.5078 +                                case 0x08: /*OR l,#32*/
 41.5079 +                                templ|=templ2;
 41.5080 +                                seteal(templ);                  if (abrt) break;
 41.5081 +                                setznp32(templ);
 41.5082 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5083 +                                break;
 41.5084 +                                case 0x10: /*ADC l,#32*/
 41.5085 +                                seteal(templ+templ2+tempc);     if (abrt) break;
 41.5086 +                                setadc32(templ,templ2);
 41.5087 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5088 +                                break;
 41.5089 +                                case 0x20: /*AND l,#32*/
 41.5090 +                                templ&=templ2;
 41.5091 +                                seteal(templ);                  if (abrt) break;
 41.5092 +                                setznp32(templ);
 41.5093 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5094 +                                break;
 41.5095 +                                case 0x18: /*SBB l,#32*/
 41.5096 +                                seteal(templ-(templ2+tempc));   if (abrt) break;
 41.5097 +                                setsbc32(templ,templ2);
 41.5098 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5099 +                                break;
 41.5100 +                                case 0x28: /*SUB l,#32*/
 41.5101 +                                seteal(templ-templ2);           if (abrt) break;
 41.5102 +                                setsub32(templ,templ2);
 41.5103 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5104 +                                break;
 41.5105 +                                case 0x30: /*XOR l,#32*/
 41.5106 +                                templ^=templ2;
 41.5107 +                                seteal(templ);                  if (abrt) break;
 41.5108 +                                setznp32(templ);
 41.5109 +                                cycles -= (mod == 3) ? timing_rr : timing_mr;
 41.5110 +                                break;
 41.5111 +                                case 0x38: /*CMP l,#32*/
 41.5112 +                                setsub32(templ,templ2);
 41.5113 +                                if (is486) cycles-=((mod==3)?1:2);
 41.5114 +                                else       cycles-=((mod==3)?2:7);
 41.5115 +                                break;
 41.5116 +                        }
 41.5117 +                        break;
 41.5118 +
 41.5119 +                        case 0x84: case 0x184: case 0x284: case 0x384: /*TEST b,reg*/
 41.5120 +                        fetchea();
 41.5121 +                        temp=geteab();          if (abrt) break;
 41.5122 +                        temp2=getr8(reg);
 41.5123 +                        setznp8(temp&temp2);
 41.5124 +                        if (is486) cycles-=((mod==3)?1:2);
 41.5125 +                        else       cycles-=((mod==3)?2:5);
 41.5126 +                        break;
 41.5127 +                        case 0x85: case 0x285: /*TEST w,reg*/
 41.5128 +                        fetchea();
 41.5129 +                        tempw=geteaw();         if (abrt) break;
 41.5130 +                        tempw2=regs[reg].w;
 41.5131 +                        setznp16(tempw&tempw2);
 41.5132 +                        if (is486) cycles-=((mod==3)?1:2);
 41.5133 +                        else       cycles-=((mod==3)?2:5);
 41.5134 +                        break;
 41.5135 +                        case 0x185: case 0x385: /*TEST l,reg*/
 41.5136 +                        fetchea();
 41.5137 +                        templ=geteal();         if (abrt) break;
 41.5138 +                        templ2=regs[reg].l;
 41.5139 +                        setznp32(templ&templ2);
 41.5140 +                        if (is486) cycles-=((mod==3)?1:2);
 41.5141 +                        else       cycles-=((mod==3)?2:5);
 41.5142 +                        break;
 41.5143 +                        case 0x86: case 0x186: case 0x286: case 0x386: /*XCHG b,reg*/
 41.5144 +                        fetchea();
 41.5145 +                        temp=geteab();          if (abrt) break;
 41.5146 +                        seteab(getr8(reg));     if (abrt) break;
 41.5147 +                        setr8(reg,temp);
 41.5148 +                        cycles-=((mod==3)?3:5);
 41.5149 +                        break;
 41.5150 +                        case 0x87: case 0x287: /*XCHG w,reg*/
 41.5151 +                        fetchea();
 41.5152 +                        tempw=geteaw();         if (abrt) break;
 41.5153 +                        seteaw(regs[reg].w);    if (abrt) break;
 41.5154 +                        regs[reg].w=tempw;
 41.5155 +                        cycles-=((mod==3)?3:5);
 41.5156 +                        break;
 41.5157 +                        case 0x187: case 0x387: /*XCHG l,reg*/
 41.5158 +                        fetchea();
 41.5159 +                        templ=geteal();         if (abrt) break;
 41.5160 +                        seteal(regs[reg].l);    if (abrt) break;
 41.5161 +                        regs[reg].l=templ;
 41.5162 +                        cycles-=((mod==3)?3:5);
 41.5163 +                        break;
 41.5164 +
 41.5165 +                        case 0x88: case 0x188: case 0x288: case 0x388: /*MOV b,reg*/
 41.5166 +                        fetchea();
 41.5167 +                        seteab(getr8(reg));
 41.5168 +                        cycles-=(is486)?1:2;
 41.5169 +                        break;
 41.5170 +                        case 0x89: case 0x289: /*MOV w,reg*/
 41.5171 +                        fetchea();
 41.5172 +                        seteaw(regs[reg].w);
 41.5173 +                        cycles-=(is486)?1:2;
 41.5174 +                        break;
 41.5175 +                        case 0x189: case 0x389: /*MOV l,reg*/
 41.5176 +                        fetchea();
 41.5177 +                        //if (output==3) pclog("Write %08X to %08X:%08X %08X %08X %08X\n",regs[reg].l,easeg,eaaddr,);
 41.5178 +                        seteal(regs[reg].l);
 41.5179 +                        cycles-=(is486)?1:2;
 41.5180 +                        break;
 41.5181 +                        case 0x8A: case 0x18A: case 0x28A: case 0x38A: /*MOV reg,b*/
 41.5182 +                        fetchea();
 41.5183 +                        temp=geteab();          if (abrt) break;
 41.5184 +                        setr8(reg,temp);
 41.5185 +                        if (is486) cycles--;
 41.5186 +                        else       cycles-=((mod==3)?2:4);
 41.5187 +                        break;
 41.5188 +                        case 0x8B: case 0x28B: /*MOV reg,w*/
 41.5189 +                        fetchea();
 41.5190 +                        tempw=geteaw();         if (abrt) break;
 41.5191 +                        regs[reg].w=tempw;
 41.5192 +                        if (is486) cycles--;
 41.5193 +                        else       cycles-=((mod==3)?2:4);
 41.5194 +                        break;
 41.5195 +                        case 0x18B: case 0x38B: /*MOV reg,l*/
 41.5196 +                        fetchea();
 41.5197 +                        templ=geteal();         if (abrt) break;
 41.5198 +                        regs[reg].l=templ;
 41.5199 +                        if (is486) cycles--;
 41.5200 +                        else       cycles-=((mod==3)?2:4);
 41.5201 +                        break;
 41.5202 +
 41.5203 +                        case 0x8C: case 0x28C: /*MOV w,sreg*/
 41.5204 +                        fetchea();
 41.5205 +//                        if (output==3) pclog("MOV sreg %02X %08X\n",rmdat,fetchdat);
 41.5206 +                        switch (rmdat&0x38)
 41.5207 +                        {
 41.5208 +                                case 0x00: /*ES*/
 41.5209 +                                seteaw(ES);
 41.5210 +                                break;
 41.5211 +                                case 0x08: /*CS*/
 41.5212 +                                seteaw(CS);
 41.5213 +                                break;
 41.5214 +                                case 0x18: /*DS*/
 41.5215 +                                if (ssegs) ds=oldds;
 41.5216 +                                seteaw(DS);
 41.5217 +                                break;
 41.5218 +                                case 0x10: /*SS*/
 41.5219 +                                if (ssegs) ss=oldss;
 41.5220 +                                seteaw(SS);
 41.5221 +                                break;
 41.5222 +                                case 0x20: /*FS*/
 41.5223 +                                seteaw(FS);
 41.5224 +                                break;
 41.5225 +                                case 0x28: /*GS*/
 41.5226 +                                seteaw(GS);
 41.5227 +                                break;
 41.5228 +                        }
 41.5229 +                        cycles-=((mod==3)?2:3);
 41.5230 +                        break;
 41.5231 +                        case 0x18C: case 0x38C: /*MOV l,sreg*/
 41.5232 +                        fetchea();
 41.5233 +                        switch (rmdat&0x38)
 41.5234 +                        {
 41.5235 +                                case 0x00: /*ES*/
 41.5236 +                                if (mod==3) regs[rm].l=ES;
 41.5237 +                                else        seteaw(ES);
 41.5238 +                                break;
 41.5239 +                                case 0x08: /*CS*/
 41.5240 +                                if (mod==3) regs[rm].l=CS;
 41.5241 +                                else        seteaw(CS);
 41.5242 +                                break;
 41.5243 +                                case 0x18: /*DS*/
 41.5244 +                                if (ssegs) ds=oldds;
 41.5245 +                                if (mod==3) regs[rm].l=DS;
 41.5246 +                                else        seteaw(DS);
 41.5247 +                                break;
 41.5248 +                                case 0x10: /*SS*/
 41.5249 +                                if (ssegs) ss=oldss;
 41.5250 +                                if (mod==3) regs[rm].l=SS;
 41.5251 +                                else        seteaw(SS);
 41.5252 +                                break;
 41.5253 +                                case 0x20: /*FS*/
 41.5254 +                                if (mod==3) regs[rm].l=FS;
 41.5255 +                                else        seteaw(FS);
 41.5256 +                                break;
 41.5257 +                                case 0x28: /*GS*/
 41.5258 +                                if (mod==3) regs[rm].l=GS;
 41.5259 +                                else        seteaw(GS);
 41.5260 +                                break;
 41.5261 +                        }
 41.5262 +                        cycles-=((mod==3)?2:3);
 41.5263 +                        break;
 41.5264 +
 41.5265 +                        case 0x8D: case 0x28D: /*LEA*/
 41.5266 +                        fetchea();
 41.5267 +                        regs[reg].w=eaaddr;
 41.5268 +                        cycles -= timing_rr;
 41.5269 +                        break;
 41.5270 +                        case 0x18D: /*LEA*/
 41.5271 +                        fetchea();
 41.5272 +                        regs[reg].l=eaaddr&0xFFFF;
 41.5273 +                        cycles -= timing_rr;
 41.5274 +                        break;
 41.5275 +                        case 0x38D: /*LEA*/
 41.5276 +                        fetchea();
 41.5277 +                        regs[reg].l=eaaddr;
 41.5278 +                        cycles -= timing_rr;
 41.5279 +                        break;
 41.5280 +
 41.5281 +                        case 0x8E: case 0x18E: case 0x28E: case 0x38E: /*MOV sreg,w*/
 41.5282 +                        fetchea();
 41.5283 +                        switch (rmdat&0x38)
 41.5284 +                        {
 41.5285 +                                case 0x00: /*ES*/
 41.5286 +                                tempw=geteaw();         if (abrt) break;
 41.5287 +                                loadseg(tempw,&_es);
 41.5288 +                                break;
 41.5289 +                                case 0x18: /*DS*/
 41.5290 +                                tempw=geteaw();         if (abrt) break;
 41.5291 +                                loadseg(tempw,&_ds);
 41.5292 +                                if (ssegs) oldds=ds;
 41.5293 +                                break;
 41.5294 +                                case 0x10: /*SS*/
 41.5295 +//                                if (output==3) pclog("geteaw\n");
 41.5296 +                                tempw=geteaw();         if (abrt) break;
 41.5297 +//                                if (output==3) pclog("loadseg\n");
 41.5298 +                                loadseg(tempw,&_ss);
 41.5299 +//                                if (output==3) pclog("done\n");
 41.5300 +                                if (ssegs) oldss=ss;
 41.5301 +                                skipnextprint=1;
 41.5302 +				noint=1;
 41.5303 +                                break;
 41.5304 +                                case 0x20: /*FS*/
 41.5305 +                                tempw=geteaw();         if (abrt) break;
 41.5306 +                                loadseg(tempw,&_fs);
 41.5307 +                                break;
 41.5308 +                                case 0x28: /*GS*/
 41.5309 +                                tempw=geteaw();         if (abrt) break;
 41.5310 +                                loadseg(tempw,&_gs);
 41.5311 +                                break;
 41.5312 +                        }
 41.5313 +                        cycles-=((mod==3)?2:5);
 41.5314 +                        break;
 41.5315 +
 41.5316 +                        case 0x8F: case 0x28F: /*POPW*/
 41.5317 +                        if (ssegs) templ2=oldss;
 41.5318 +                        else       templ2=ss;
 41.5319 +                        if (stack32)
 41.5320 +                        {
 41.5321 +                                tempw=readmemw(templ2,ESP);     if (abrt) break;
 41.5322 +                                ESP+=2;
 41.5323 +                        }
 41.5324 +                        else
 41.5325 +                        {
 41.5326 +                                tempw=readmemw(templ2,SP);      if (abrt) break;
 41.5327 +                                SP+=2;
 41.5328 +                        }
 41.5329 +                        fetchea();
 41.5330 +                        if (ssegs) ss=oldss;
 41.5331 +                        seteaw(tempw);
 41.5332 +                        if (abrt)
 41.5333 +                        {
 41.5334 +                                if (stack32) ESP-=2;
 41.5335 +                                else         SP-=2;
 41.5336 +                        }
 41.5337 +                        if (is486) cycles-=((mod==3)?1:6);
 41.5338 +                        else       cycles-=((mod==3)?4:5);
 41.5339 +                        break;
 41.5340 +                        case 0x18F: case 0x38F: /*POPL*/
 41.5341 +                        if (ssegs) templ2=oldss;
 41.5342 +                        else       templ2=ss;
 41.5343 +                        if (stack32)
 41.5344 +                        {
 41.5345 +                                templ=readmeml(templ2,ESP);     if (abrt) break;
 41.5346 +                                ESP+=4;
 41.5347 +                        }
 41.5348 +                        else
 41.5349 +                        {
 41.5350 +                                templ=readmeml(templ2,SP);      if (abrt) break;
 41.5351 +                                SP+=4;
 41.5352 +                        }
 41.5353 +                        fetchea();
 41.5354 +                        if (ssegs) ss=oldss;
 41.5355 +                        seteal(templ);
 41.5356 +                        if (abrt)
 41.5357 +                        {
 41.5358 +                                if (stack32) ESP-=4;
 41.5359 +                                else         SP-=4;
 41.5360 +                        }
 41.5361 +                        if (is486) cycles-=((mod==3)?1:6);
 41.5362 +                        else       cycles-=((mod==3)?4:5);
 41.5363 +                        break;
 41.5364 +
 41.5365 +                        case 0x90: case 0x190: case 0x290: case 0x390: /*NOP*/
 41.5366 +                        cycles-=(is486)?1:3;
 41.5367 +                        break;
 41.5368 +
 41.5369 +                        case 0x91: case 0x92: case 0x93: /*XCHG AX*/
 41.5370 +                        case 0x94: case 0x95: case 0x96: case 0x97:
 41.5371 +                        case 0x291: case 0x292: case 0x293:
 41.5372 +                        case 0x294: case 0x295: case 0x296: case 0x297:
 41.5373 +                        tempw=AX;
 41.5374 +                        AX=regs[opcode&7].w;
 41.5375 +                        regs[opcode&7].w=tempw;
 41.5376 +                        cycles-=3;
 41.5377 +                        break;
 41.5378 +                        case 0x191: case 0x192: case 0x193: /*XCHG EAX*/
 41.5379 +                        case 0x194: case 0x195: case 0x196: case 0x197:
 41.5380 +                        case 0x391: case 0x392: case 0x393: /*XCHG EAX*/
 41.5381 +                        case 0x394: case 0x395: case 0x396: case 0x397:
 41.5382 +                        templ=EAX;
 41.5383 +                        EAX=regs[opcode&7].l;
 41.5384 +                        regs[opcode&7].l=templ;
 41.5385 +                        cycles-=3;
 41.5386 +                        break;
 41.5387 +
 41.5388 +                        case 0x98: case 0x298: /*CBW*/
 41.5389 +                        AH=(AL&0x80)?0xFF:0;
 41.5390 +                        cycles-=3;
 41.5391 +                        break;
 41.5392 +                        case 0x198: case 0x398: /*CWDE*/
 41.5393 +                        EAX=(AX&0x8000)?(0xFFFF0000|AX):AX;
 41.5394 +                        cycles-=3;
 41.5395 +                        break;
 41.5396 +                        case 0x99: case 0x299: /*CWD*/
 41.5397 +                        DX=(AX&0x8000)?0xFFFF:0;
 41.5398 +                        cycles-=2;
 41.5399 +                        break;
 41.5400 +                        case 0x199: case 0x399: /*CDQ*/
 41.5401 +                        EDX=(EAX&0x80000000)?0xFFFFFFFF:0;
 41.5402 +                        cycles-=2;
 41.5403 +                        break;
 41.5404 +                        case 0x9A: case 0x29A: /*CALL FAR*/
 41.5405 +                        tempw=getword();
 41.5406 +                        tempw2=getword();       if (abrt) break;
 41.5407 +                        if (output == 3) pclog("Call far %04X:%04X\n",tempw2,tempw);
 41.5408 +                        tempw3=CS;
 41.5409 +                        templ2 = pc;
 41.5410 +                        if (output) pclog("Call far %08X\n",templ2);
 41.5411 +                        if (ssegs) ss=oldss;
 41.5412 +                        oxpc=pc;
 41.5413 +                        pc=tempw;
 41.5414 +                        optype=CALL;
 41.5415 +                        cgate32=0;
 41.5416 +                        if (output == 3) pclog("Load CS\n");
 41.5417 +                        if (msw&1) loadcscall(tempw2);
 41.5418 +                        else       loadcs(tempw2);
 41.5419 +                        if (output == 3) pclog("%i %i\n", abrt, cgate32);
 41.5420 +                        optype=0;
 41.5421 +//                        if (output==3) pclog("CALL FAR 16 complete\n");
 41.5422 +                        if (abrt) break;
 41.5423 +                        oldss=ss;
 41.5424 +                        if (cgate32) goto writecall32;
 41.5425 +                writecall16:
 41.5426 +                        cgate16=0;
 41.5427 +                        if (stack32)
 41.5428 +                        {
 41.5429 +                                writememw(ss,ESP-2,tempw3);
 41.5430 +                                writememw(ss,ESP-4,templ2);     if (abrt) break;
 41.5431 +                                ESP-=4;
 41.5432 +                        }
 41.5433 +                        else
 41.5434 +                        {
 41.5435 +                                writememw(ss,(SP-2)&0xFFFF,tempw3);
 41.5436 +                                if (output) pclog("Write CS to %04X:%04X\n",SS,SP-2);
 41.5437 +                                writememw(ss,(SP-4)&0xFFFF,templ2);     if (abrt) break;
 41.5438 +                                if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,SP-4);
 41.5439 +                                SP-=4;
 41.5440 +                        }
 41.5441 +                        cycles-=(is486)?18:17;
 41.5442 +                        break;
 41.5443 +                        case 0x19A: case 0x39A: /*CALL FAR*/
 41.5444 +//                        if (output==3) pclog("CF 1 %08X\n",pc);
 41.5445 +                        templ=getword(); templ|=(getword()<<16);
 41.5446 +//                        if (output==3) pclog("CF 2\n");
 41.5447 +                        tempw2=getword();       if (abrt) break;
 41.5448 +//                        if (output==3) pclog("CF 3 %04X:%08X\n",tempw2,templ);
 41.5449 +                        tempw3=CS;
 41.5450 +                        templ2 = pc;
 41.5451 +                        if (ssegs) ss=oldss;
 41.5452 +                        oxpc=pc;
 41.5453 +                        pc=templ;
 41.5454 +                        optype=CALL;
 41.5455 +                        cgate16=0;
 41.5456 +//                        if (output==3) pclog("Load CS\n");
 41.5457 +                        if (msw&1) loadcscall(tempw2);
 41.5458 +                        else       loadcs(tempw2);
 41.5459 +//                        if (output==3) pclog("%i %i\n",notpresent,abrt);
 41.5460 +                        optype=0;
 41.5461 +//                        if (output==3) pclog("CALL FAR 32 complete\n");
 41.5462 +                        if (abrt) break;
 41.5463 +                        oldss=ss;
 41.5464 +                        if (cgate16) goto writecall16;
 41.5465 +                writecall32:
 41.5466 +                        cgate32=0;
 41.5467 +                        if (stack32)
 41.5468 +                        {
 41.5469 +                                writememl(ss,ESP-4,tempw3);
 41.5470 +                                writememl(ss,ESP-8,templ2);             if (abrt) break;
 41.5471 +                                if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,ESP-8);
 41.5472 +                                ESP-=8;
 41.5473 +                        }
 41.5474 +                        else
 41.5475 +                        {
 41.5476 +                                writememl(ss,(SP-4)&0xFFFF,tempw3);
 41.5477 +                                writememl(ss,(SP-8)&0xFFFF,templ2);     if (abrt) break;
 41.5478 +                                if (output) pclog("Write PC %08X to %04X:%04X\n", templ2, SS,SP-8);
 41.5479 +                                SP-=8;
 41.5480 +                        }
 41.5481 +                        cycles-=(is486)?18:17;
 41.5482 +                        break;
 41.5483 +                        case 0x9B: case 0x19B: case 0x29B: case 0x39B: /*WAIT*/
 41.5484 +                        cycles-=4;
 41.5485 +                        break;
 41.5486 +                        case 0x9C: case 0x29C: /*PUSHF*/
 41.5487 +                        if (ssegs) ss=oldss;
 41.5488 +                        if ((eflags&VM_FLAG) && (IOPL<3))
 41.5489 +                        {
 41.5490 +                                x86gpf(NULL,0);
 41.5491 +                                break;
 41.5492 +                        }
 41.5493 +                        if (stack32)
 41.5494 +                        {
 41.5495 +                                writememw(ss,ESP-2,flags);              if (abrt) break;
 41.5496 +                                ESP-=2;
 41.5497 +                        }
 41.5498 +                        else
 41.5499 +                        {
 41.5500 +                                writememw(ss,((SP-2)&0xFFFF),flags);    if (abrt) break;
 41.5501 +                                SP-=2;
 41.5502 +                        }
 41.5503 +                        cycles-=4;
 41.5504 +                        break;
 41.5505 +                        case 0x19C: case 0x39C: /*PUSHFD*/
 41.5506 +//                        pclog("PUSHFD %04X(%08X):%08X\n",CS,cs,pc);
 41.5507 +                        if (ssegs) ss=oldss;
 41.5508 +                        if ((eflags&VM_FLAG) && (IOPL<3))
 41.5509 +                        {
 41.5510 +                                x86gpf(NULL,0);
 41.5511 +                                break;
 41.5512 +                        }
 41.5513 +                        if (CPUID) tempw=eflags&0x24;
 41.5514 +                        else       tempw=eflags&4;
 41.5515 +                        if (stack32)
 41.5516 +                        {
 41.5517 +                                writememw(ss,ESP-2,tempw);
 41.5518 +                                writememw(ss,ESP-4,flags);              if (abrt) break;
 41.5519 +                                ESP-=4;
 41.5520 +//                                if (output==3) pclog("Pushing %04X %04X\n",eflags,flags);
 41.5521 +                        }
 41.5522 +                        else
 41.5523 +                        {
 41.5524 +                                writememw(ss,((SP-2)&0xFFFF),tempw);
 41.5525 +                                writememw(ss,((SP-4)&0xFFFF),flags);    if (abrt) break;
 41.5526 +                                SP-=4;
 41.5527 +                        }
 41.5528 +                        cycles-=4;
 41.5529 +                        break;
 41.5530 +                        case 0x9D: case 0x29D: /*POPF*/
 41.5531 +//                        if (CS!=0x21 && CS!=0xF000) pclog("POPF %04X:%04X\n",CS,pc);
 41.5532 +                        if (ssegs) ss=oldss;
 41.5533 +                        if ((eflags&VM_FLAG) && (IOPL<3))
 41.5534 +                        {
 41.5535 +                                x86gpf(NULL,0);
 41.5536 +                                break;
 41.5537 +                        }
 41.5538 +                        if (stack32)
 41.5539 +                        {
 41.5540 +                                tempw=readmemw(ss,ESP);                 if (abrt) break;
 41.5541 +                                ESP+=2;
 41.5542 +                        }
 41.5543 +                        else
 41.5544 +                        {
 41.5545 +                                tempw=readmemw(ss,SP);                  if (abrt) break;
 41.5546 +                                SP+=2;
 41.5547 +                        }
 41.5548 +//                        pclog("POPF! %i %i %i\n",CPL,msw&1,IOPLp);
 41.5549 +                        if (!(CPL) || !(msw&1)) flags=(tempw&0xFFD5)|2;
 41.5550 +                        else if (IOPLp) flags=(flags&0x3000)|(tempw&0xCFD5)|2;
 41.5551 +                        else            flags=(flags&0xF200)|(tempw&0x0DD5)|2;
 41.5552 +//                        if (flags==0xF000) pclog("POPF - flags now F000 %04X(%06X):%04X %08X %08X %08X\n",CS,cs,pc,old8,old82,old83);
 41.5553 +                        cycles-=5;
 41.5554 +                        break;
 41.5555 +                        case 0x19D: case 0x39D: /*POPFD*/
 41.5556 +                        if (ssegs) ss=oldss;
 41.5557 +                        if ((eflags&VM_FLAG) && (IOPL<3))
 41.5558 +                        {
 41.5559 +                                x86gpf(NULL,0);
 41.5560 +                                break;
 41.5561 +                        }
 41.5562 +                        if (stack32)
 41.5563 +                        {
 41.5564 +                                tempw=readmemw(ss,ESP);
 41.5565 +                                tempw2=readmemw(ss,ESP+2);              if (abrt) break;
 41.5566 +                                ESP+=4;
 41.5567 +                        }
 41.5568 +                        else
 41.5569 +                        {
 41.5570 +                                tempw=readmemw(ss,SP);
 41.5571 +                                tempw2=readmemw(ss,SP+2);               if (abrt) break;
 41.5572 +                                SP+=4;
 41.5573 +                        }
 41.5574 +//                        eflags|=0x200000;
 41.5575 +                        if (!(CPL) || !(msw&1)) flags=(tempw&0xFFD5)|2;
 41.5576 +                        else if (IOPLp) flags=(flags&0x3000)|(tempw&0xCFD5)|2;
 41.5577 +                        else            flags=(flags&0xF200)|(tempw&0x0DD5)|2;
 41.5578 +                        tempw2&=(is486)?0x24:0;
 41.5579 +                        tempw2|=(eflags&3);
 41.5580 +                        if (CPUID) eflags=tempw2&0x27;
 41.5581 +                        else if (is486) eflags=tempw2&7;
 41.5582 +                        else       eflags=tempw2&3;
 41.5583 +//                        if (flags==0xF000) pclog("POPF - flags now F000 %04X(%06X):%04X %08X %08X %08X\n",CS,cs,pc,old8,old82,old83);
 41.5584 +                        cycles-=5;
 41.5585 +                        break;
 41.5586 +                        case 0x9E: case 0x19E: case 0x29E: case 0x39E: /*SAHF*/
 41.5587 +                        flags=(flags&0xFF00)|(AH&0xD5)|2;
 41.5588 +                        cycles-=3;
 41.5589 +                        break;
 41.5590 +                        case 0x9F: case 0x19F: case 0x29F: case 0x39F: /*LAHF*/
 41.5591 +                        AH=flags&0xFF;
 41.5592 +                        cycles-=3;
 41.5593 +                        break;
 41.5594 +
 41.5595 +                        case 0xA0: case 0x1A0: /*MOV AL,(w)*/
 41.5596 +                        addr=getword(); if (abrt) break;
 41.5597 +                        temp=readmemb(ds,addr);         if (abrt) break;
 41.5598 +                        AL=temp;
 41.5599 +                        cycles-=(is486)?1:4;
 41.5600 +                        break;
 41.5601 +                        case 0x2A0: case 0x3A0: /*MOV AL,(l)*/
 41.5602 +                        addr=getlong(); if (abrt) break;
 41.5603 +                        temp=readmemb(ds,addr);         if (abrt) break;
 41.5604 +                        AL=temp;
 41.5605 +                        cycles-=(is486)?1:4;
 41.5606 +                        break;
 41.5607 +                        case 0xA1: /*MOV AX,(w)*/
 41.5608 +                        addr=getword(); if (abrt) break;
 41.5609 +                        tempw=readmemw(ds,addr);        if (abrt) break;
 41.5610 +                        AX=tempw;
 41.5611 +                        cycles-=(is486)?1:4;
 41.5612 +                        break;
 41.5613 +                        case 0x1A1: /*MOV EAX,(w)*/
 41.5614 +                        addr=getword(); if (abrt) break;
 41.5615 +                        templ=readmeml(ds,addr);        if (abrt) break;
 41.5616 +                        EAX=templ;
 41.5617 +                        cycles-=(is486)?1:4;
 41.5618 +                        break;
 41.5619 +                        case 0x2A1: /*MOV AX,(l)*/
 41.5620 +                        addr=getlong(); if (abrt) break;
 41.5621 +                        tempw=readmemw(ds,addr);        if (abrt) break;
 41.5622 +                        AX=tempw;
 41.5623 +                        cycles-=(is486)?1:4;
 41.5624 +                        break;
 41.5625 +                        case 0x3A1: /*MOV EAX,(l)*/
 41.5626 +                        addr=getlong(); if (abrt) break;
 41.5627 +                        templ=readmeml(ds,addr);        if (abrt) break;
 41.5628 +                        EAX=templ;
 41.5629 +                        cycles-=(is486)?1:4;
 41.5630 +                        break;
 41.5631 +                        case 0xA2: case 0x1A2: /*MOV (w),AL*/
 41.5632 +                        addr=getword(); if (abrt) break;
 41.5633 +                        writememb(ds,addr,AL);
 41.5634 +                        cycles-=(is486)?1:2;
 41.5635 +                        break;
 41.5636 +                        case 0x2A2: case 0x3A2: /*MOV (l),AL*/
 41.5637 +                        addr=getlong(); if (abrt) break;
 41.5638 +                        writememb(ds,addr,AL);
 41.5639 +                        cycles-=(is486)?1:2;
 41.5640 +                        break;
 41.5641 +                        case 0xA3: /*MOV (w),AX*/
 41.5642 +                        addr=getword(); if (abrt) break;
 41.5643 +                        writememw(ds,addr,AX);
 41.5644 +                        cycles-=(is486)?1:2;
 41.5645 +                        break;
 41.5646 +                        case 0x1A3: /*MOV (w),EAX*/
 41.5647 +                        addr=getword(); if (abrt) break;
 41.5648 +                        writememl(ds,addr,EAX);
 41.5649 +                        cycles-=(is486)?1:2;
 41.5650 +                        break;
 41.5651 +                        case 0x2A3: /*MOV (l),AX*/
 41.5652 +                        addr=getlong(); if (abrt) break;
 41.5653 +                        writememw(ds,addr,AX);
 41.5654 +                        cycles-=(is486)?1:2;
 41.5655 +                        break;
 41.5656 +                        case 0x3A3: /*MOV (l),EAX*/
 41.5657 +                        addr=getlong(); if (abrt) break;
 41.5658 +                        writememl(ds,addr,EAX);
 41.5659 +                        cycles-=(is486)?1:2;
 41.5660 +                        break;
 41.5661 +
 41.5662 +                        case 0xA4: case 0x1A4: /*MOVSB*/
 41.5663 +                        temp=readmemb(ds,SI);  if (abrt) break;
 41.5664 +                        writememb(es,DI,temp); if (abrt) break;
 41.5665 +                        if (flags&D_FLAG) { DI--; SI--; }
 41.5666 +                        else              { DI++; SI++; }
 41.5667 +                        cycles-=7;
 41.5668 +                        break;
 41.5669 +                        case 0x2A4: case 0x3A4: /*MOVSB*/
 41.5670 +                        temp=readmemb(ds,ESI);  if (abrt) break;
 41.5671 +                        writememb(es,EDI,temp); if (abrt) break;
 41.5672 +                        if (flags&D_FLAG) { EDI--; ESI--; }
 41.5673 +                        else              { EDI++; ESI++; }
 41.5674 +                        cycles-=7;
 41.5675 +                        break;
 41.5676 +                        case 0xA5: /*MOVSW*/
 41.5677 +                        tempw=readmemw(ds,SI);  if (abrt) break;
 41.5678 +                        writememw(es,DI,tempw); if (abrt) break;
 41.5679 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
 41.5680 +                        else              { DI+=2; SI+=2; }
 41.5681 +                        cycles-=7;
 41.5682 +                        break;
 41.5683 +                        case 0x2A5: /*MOVSW*/
 41.5684 +                        tempw=readmemw(ds,ESI);  if (abrt) break;
 41.5685 +                        writememw(es,EDI,tempw); if (abrt) break;
 41.5686 +                        if (flags&D_FLAG) { EDI-=2; ESI-=2; }
 41.5687 +                        else              { EDI+=2; ESI+=2; }
 41.5688 +                        cycles-=7;
 41.5689 +                        break;
 41.5690 +                        case 0x1A5: /*MOVSL*/
 41.5691 +                        templ=readmeml(ds,SI);  if (abrt) break;
 41.5692 +                        writememl(es,DI,templ); if (abrt) break;
 41.5693 +                        if (flags&D_FLAG) { DI-=4; SI-=4; }
 41.5694 +                        else              { DI+=4; SI+=4; }
 41.5695 +                        cycles-=7;
 41.5696 +                        break;
 41.5697 +                        case 0x3A5: /*MOVSL*/
 41.5698 +                        templ=readmeml(ds,ESI);  if (abrt) break;
 41.5699 +                        writememl(es,EDI,templ); if (abrt) break;
 41.5700 +                        if (flags&D_FLAG) { EDI-=4; ESI-=4; }
 41.5701 +                        else              { EDI+=4; ESI+=4; }
 41.5702 +                        cycles-=7;
 41.5703 +                        break;
 41.5704 +                        case 0xA6: case 0x1A6: /*CMPSB*/
 41.5705 +                        temp =readmemb(ds,SI);
 41.5706 +                        temp2=readmemb(es,DI);
 41.5707 +                        if (abrt) break;
 41.5708 +                        setsub8(temp,temp2);
 41.5709 +                        if (flags&D_FLAG) { DI--; SI--; }
 41.5710 +                        else              { DI++; SI++; }
 41.5711 +                        cycles-=(is486)?8:10;
 41.5712 +                        break;
 41.5713 +                        case 0x2A6: case 0x3A6: /*CMPSB*/
 41.5714 +                        temp =readmemb(ds,ESI);
 41.5715 +                        temp2=readmemb(es,EDI);
 41.5716 +                        if (abrt) break;
 41.5717 +                        setsub8(temp,temp2);
 41.5718 +                        if (flags&D_FLAG) { EDI--; ESI--; }
 41.5719 +                        else              { EDI++; ESI++; }
 41.5720 +                        cycles-=(is486)?8:10;
 41.5721 +                        break;
 41.5722 +                        case 0xA7: /*CMPSW*/
 41.5723 +                        tempw =readmemw(ds,SI);
 41.5724 +                        tempw2=readmemw(es,DI);
 41.5725 +                        if (abrt) break;
 41.5726 +                        setsub16(tempw,tempw2);
 41.5727 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
 41.5728 +                        else              { DI+=2; SI+=2; }
 41.5729 +                        cycles-=(is486)?8:10;
 41.5730 +                        break;
 41.5731 +                        case 0x1A7: /*CMPSL*/
 41.5732 +                        templ =readmeml(ds,SI);
 41.5733 +                        templ2=readmeml(es,DI);
 41.5734 +                        if (abrt) break;
 41.5735 +                        setsub32(templ,templ2);
 41.5736 +                        if (flags&D_FLAG) { DI-=4; SI-=4; }
 41.5737 +                        else              { DI+=4; SI+=4; }
 41.5738 +                        cycles-=(is486)?8:10;
 41.5739 +                        break;
 41.5740 +                        case 0x2A7: /*CMPSW*/
 41.5741 +                        tempw =readmemw(ds,ESI);
 41.5742 +                        tempw2=readmemw(es,EDI);
 41.5743 +                        if (abrt) break;
 41.5744 +                        setsub16(tempw,tempw2);
 41.5745 +                        if (flags&D_FLAG) { EDI-=2; ESI-=2; }
 41.5746 +                        else              { EDI+=2; ESI+=2; }
 41.5747 +                        cycles-=(is486)?8:10;
 41.5748 +                        break;
 41.5749 +                        case 0x3A7: /*CMPSL*/
 41.5750 +                        templ =readmeml(ds,ESI);
 41.5751 +                        templ2=readmeml(es,EDI);
 41.5752 +                        if (abrt) break;
 41.5753 +                        setsub32(templ,templ2);
 41.5754 +                        if (flags&D_FLAG) { EDI-=4; ESI-=4; }
 41.5755 +                        else              { EDI+=4; ESI+=4; }
 41.5756 +                        cycles-=(is486)?8:10;
 41.5757 +                        break;
 41.5758 +                        case 0xA8: case 0x1A8: case 0x2A8: case 0x3A8: /*TEST AL,#8*/
 41.5759 +                        temp=getbytef();
 41.5760 +                        setznp8(AL&temp);
 41.5761 +                        cycles -= timing_rr;
 41.5762 +                        break;
 41.5763 +                        case 0xA9: case 0x2A9: /*TEST AX,#16*/
 41.5764 +                        tempw=getwordf();
 41.5765 +                        setznp16(AX&tempw);
 41.5766 +                        cycles -= timing_rr;
 41.5767 +                        break;
 41.5768 +                        case 0x1A9: case 0x3A9: /*TEST EAX,#32*/
 41.5769 +                        templ=getlong();        if (abrt) break;
 41.5770 +                        setznp32(EAX&templ);
 41.5771 +                        cycles -= timing_rr;
 41.5772 +                        break;
 41.5773 +                        case 0xAA: case 0x1AA: /*STOSB*/
 41.5774 +                        writememb(es,DI,AL);    if (abrt) break;
 41.5775 +                        if (flags&D_FLAG) DI--;
 41.5776 +                        else              DI++;
 41.5777 +                        cycles-=4;
 41.5778 +                        break;
 41.5779 +                        case 0x2AA: case 0x3AA: /*STOSB*/
 41.5780 +                        writememb(es,EDI,AL);   if (abrt) break;
 41.5781 +                        if (flags&D_FLAG) EDI--;
 41.5782 +                        else              EDI++;
 41.5783 +                        cycles-=4;
 41.5784 +                        break;
 41.5785 +                        case 0xAB: /*STOSW*/
 41.5786 +                        writememw(es,DI,AX);    if (abrt) break;
 41.5787 +                        if (flags&D_FLAG) DI-=2;
 41.5788 +                        else              DI+=2;
 41.5789 +                        cycles-=4;
 41.5790 +                        break;
 41.5791 +                        case 0x1AB: /*STOSL*/
 41.5792 +                        writememl(es,DI,EAX);   if (abrt) break;
 41.5793 +                        if (flags&D_FLAG) DI-=4;
 41.5794 +                        else              DI+=4;
 41.5795 +                        cycles-=4;
 41.5796 +                        break;
 41.5797 +                        case 0x2AB: /*STOSW*/
 41.5798 +                        writememw(es,EDI,AX);   if (abrt) break;
 41.5799 +                        if (flags&D_FLAG) EDI-=2;
 41.5800 +                        else              EDI+=2;
 41.5801 +                        cycles-=4;
 41.5802 +                        break;
 41.5803 +                        case 0x3AB: /*STOSL*/
 41.5804 +                        writememl(es,EDI,EAX);  if (abrt) break;
 41.5805 +                        if (flags&D_FLAG) EDI-=4;
 41.5806 +                        else              EDI+=4;
 41.5807 +                        cycles-=4;
 41.5808 +                        break;
 41.5809 +                        case 0xAC: case 0x1AC: /*LODSB*/
 41.5810 +                        temp=readmemb(ds,SI);
 41.5811 +                        if (abrt) break;
 41.5812 +                        AL=temp;
 41.5813 +//                        if (output==3) pclog("LODSB %02X from %05X:%04X\n",AL,ds,SI);
 41.5814 +                        if (flags&D_FLAG) SI--;
 41.5815 +                        else              SI++;
 41.5816 +                        cycles-=5;
 41.5817 +                        break;
 41.5818 +                        case 0x2AC: case 0x3AC: /*LODSB*/
 41.5819 +                        temp=readmemb(ds,ESI);
 41.5820 +                        if (abrt) break;
 41.5821 +                        AL=temp;
 41.5822 +                        if (flags&D_FLAG) ESI--;
 41.5823 +                        else              ESI++;
 41.5824 +                        cycles-=5;
 41.5825 +                        break;
 41.5826 +                        case 0xAD: /*LODSW*/
 41.5827 +                        tempw=readmemw(ds,SI);
 41.5828 +                        if (abrt) break;
 41.5829 +                        AX=tempw;
 41.5830 +//                        if (output) pclog("Load from %05X:%04X\n",ds,SI);
 41.5831 +                        if (flags&D_FLAG) SI-=2;
 41.5832 +                        else              SI+=2;
 41.5833 +                        cycles-=5;
 41.5834 +                        break;
 41.5835 +                        case 0x1AD: /*LODSL*/
 41.5836 +                        templ=readmeml(ds,SI);
 41.5837 +                        if (abrt) break;
 41.5838 +                        EAX=templ;
 41.5839 +                        if (flags&D_FLAG) SI-=4;
 41.5840 +                        else              SI+=4;
 41.5841 +                        cycles-=5;
 41.5842 +                        break;
 41.5843 +                        case 0x2AD: /*LODSW*/
 41.5844 +                        tempw=readmemw(ds,ESI);
 41.5845 +                        if (abrt) break;
 41.5846 +                        AX=tempw;
 41.5847 +                        if (flags&D_FLAG) ESI-=2;
 41.5848 +                        else              ESI+=2;
 41.5849 +                        cycles-=5;
 41.5850 +                        break;
 41.5851 +                        case 0x3AD: /*LODSL*/
 41.5852 +                        templ=readmeml(ds,ESI);
 41.5853 +                        if (abrt) break;
 41.5854 +                        EAX=templ;
 41.5855 +                        if (flags&D_FLAG) ESI-=4;
 41.5856 +                        else              ESI+=4;
 41.5857 +                        cycles-=5;
 41.5858 +                        break;
 41.5859 +                        case 0xAE: case 0x1AE: /*SCASB*/
 41.5860 +                        temp=readmemb(es,DI);
 41.5861 +                        if (abrt) break;
 41.5862 +                        setsub8(AL,temp);
 41.5863 +                        if (flags&D_FLAG) DI--;
 41.5864 +                        else              DI++;
 41.5865 +                        cycles-=7;
 41.5866 +                        break;
 41.5867 +                        case 0x2AE: case 0x3AE: /*SCASB*/
 41.5868 +                        temp=readmemb(es,EDI);
 41.5869 +                        if (abrt) break;
 41.5870 +                        setsub8(AL,temp);
 41.5871 +                        if (flags&D_FLAG) EDI--;
 41.5872 +                        else              EDI++;
 41.5873 +                        cycles-=7;
 41.5874 +                        break;
 41.5875 +                        case 0xAF: /*SCASW*/
 41.5876 +                        tempw=readmemw(es,DI);
 41.5877 +                        if (abrt) break;
 41.5878 +                        setsub16(AX,tempw);
 41.5879 +                        if (flags&D_FLAG) DI-=2;
 41.5880 +                        else              DI+=2;
 41.5881 +                        cycles-=7;
 41.5882 +                        break;
 41.5883 +                        case 0x1AF: /*SCASL*/
 41.5884 +                        templ=readmeml(es,DI);
 41.5885 +                        if (abrt) break;
 41.5886 +                        setsub32(EAX,templ);
 41.5887 +                        if (flags&D_FLAG) DI-=4;
 41.5888 +                        else              DI+=4;
 41.5889 +                        cycles-=7;
 41.5890 +                        break;
 41.5891 +                        case 0x2AF: /*SCASW*/
 41.5892 +                        tempw=readmemw(es,EDI);
 41.5893 +                        if (abrt) break;
 41.5894 +                        setsub16(AX,tempw);
 41.5895 +                        if (flags&D_FLAG) EDI-=2;
 41.5896 +                        else              EDI+=2;
 41.5897 +                        cycles-=7;
 41.5898 +                        break;
 41.5899 +                        case 0x3AF: /*SCASL*/
 41.5900 +                        templ=readmeml(es,EDI);
 41.5901 +                        if (abrt) break;
 41.5902 +                        setsub32(EAX,templ);
 41.5903 +                        if (flags&D_FLAG) EDI-=4;
 41.5904 +                        else              EDI+=4;
 41.5905 +                        cycles-=7;
 41.5906 +                        break;
 41.5907 +
 41.5908 +                        case 0xB0: case 0x1B0: case 0x2B0: case 0x3B0: /*MOV AL,#8*/
 41.5909 +                        AL=getbytef();
 41.5910 +                        cycles -= timing_rr;
 41.5911 +                        break;
 41.5912 +                        case 0xB1: case 0x1B1: case 0x2B1: case 0x3B1: /*MOV CL,#8*/
 41.5913 +                        CL=getbytef();
 41.5914 +                        cycles -= timing_rr;
 41.5915 +                        break;
 41.5916 +                        case 0xB2: case 0x1B2: case 0x2B2: case 0x3B2: /*MOV DL,#8*/
 41.5917 +                        DL=getbytef();
 41.5918 +                        cycles -= timing_rr;
 41.5919 +                        break;
 41.5920 +                        case 0xB3: case 0x1B3: case 0x2B3: case 0x3B3: /*MOV BL,#8*/
 41.5921 +                        BL=getbytef();
 41.5922 +                        cycles -= timing_rr;
 41.5923 +                        break;
 41.5924 +                        case 0xB4: case 0x1B4: case 0x2B4: case 0x3B4: /*MOV AH,#8*/
 41.5925 +                        AH=getbytef();
 41.5926 +                        cycles -= timing_rr;
 41.5927 +                        break;
 41.5928 +                        case 0xB5: case 0x1B5: case 0x2B5: case 0x3B5: /*MOV CH,#8*/
 41.5929 +                        CH=getbytef();
 41.5930 +                        cycles -= timing_rr;
 41.5931 +                        break;
 41.5932 +                        case 0xB6: case 0x1B6: case 0x2B6: case 0x3B6: /*MOV DH,#8*/
 41.5933 +                        DH=getbytef();
 41.5934 +                        cycles -= timing_rr;
 41.5935 +                        break;
 41.5936 +                        case 0xB7: case 0x1B7: case 0x2B7: case 0x3B7: /*MOV BH,#8*/
 41.5937 +                        BH=getbytef();
 41.5938 +                        cycles -= timing_rr;
 41.5939 +                        break;
 41.5940 +                        case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/
 41.5941 +                        case 0xBC: case 0xBD: case 0xBE: case 0xBF:
 41.5942 +                        case 0x2B8: case 0x2B9: case 0x2BA: case 0x2BB:
 41.5943 +                        case 0x2BC: case 0x2BD: case 0x2BE: case 0x2BF:
 41.5944 +                        regs[opcode&7].w=getwordf();
 41.5945 +                        cycles -= timing_rr;
 41.5946 +                        break;
 41.5947 +                        case 0x1B8: case 0x1B9: case 0x1BA: case 0x1BB: /*MOV reg,#32*/
 41.5948 +                        case 0x1BC: case 0x1BD: case 0x1BE: case 0x1BF:
 41.5949 +                        case 0x3B8: case 0x3B9: case 0x3BA: case 0x3BB:
 41.5950 +                        case 0x3BC: case 0x3BD: case 0x3BE: case 0x3BF:
 41.5951 +                        templ=getlong();     if (abrt) break;
 41.5952 +                        regs[opcode&7].l=templ;
 41.5953 +                        cycles -= timing_rr;
 41.5954 +                        break;
 41.5955 +
 41.5956 +                        case 0xC0: case 0x1C0: case 0x2C0: case 0x3C0:
 41.5957 +                        fetchea();
 41.5958 +                        c=readmemb(cs,pc); pc++;
 41.5959 +                        temp=geteab();          if (abrt) break;
 41.5960 +                        c&=31;
 41.5961 +                        if (!c) break;
 41.5962 +                        switch (rmdat&0x38)
 41.5963 +                        {
 41.5964 +                                case 0x00: /*ROL b,CL*/
 41.5965 +                                while (c>0)
 41.5966 +                                {
 41.5967 +                                        temp2=(temp&0x80)?1:0;
 41.5968 +                                        temp=(temp<<1)|temp2;
 41.5969 +                                        c--;
 41.5970 +                                }
 41.5971 +                                seteab(temp);   if (abrt) break;
 41.5972 +                                flags&=~(C_FLAG|V_FLAG);
 41.5973 +                                if (temp2) flags|=C_FLAG;
 41.5974 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.5975 +                                cycles-=((mod==3)?3:7);
 41.5976 +                                break;
 41.5977 +                                case 0x08: /*ROR b,CL*/
 41.5978 +                                while (c>0)
 41.5979 +                                {
 41.5980 +                                        temp2=temp&1;
 41.5981 +                                        temp>>=1;
 41.5982 +                                        if (temp2) temp|=0x80;
 41.5983 +                                        c--;
 41.5984 +                                }
 41.5985 +                                seteab(temp);   if (abrt) break;
 41.5986 +                                flags&=~(C_FLAG|V_FLAG);
 41.5987 +                                if (temp2) flags|=C_FLAG;
 41.5988 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.5989 +                                cycles-=((mod==3)?3:7);
 41.5990 +                                break;
 41.5991 +                                case 0x10: /*RCL b,CL*/
 41.5992 +                                temp2=flags&C_FLAG;
 41.5993 +                                while (c>0)
 41.5994 +                                {
 41.5995 +                                        tempc=(temp2)?1:0;
 41.5996 +                                        temp2=temp&0x80;
 41.5997 +                                        temp=(temp<<1)|tempc;
 41.5998 +                                        c--;
 41.5999 +                                        if (is486) cycles--;
 41.6000 +                                }
 41.6001 +                                seteab(temp);   if (abrt) break;
 41.6002 +                                flags&=~(C_FLAG|V_FLAG);
 41.6003 +                                if (temp2) flags|=C_FLAG;
 41.6004 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.6005 +                                cycles-=((mod==3)?9:10);
 41.6006 +                                break;
 41.6007 +                                case 0x18: /*RCR b,CL*/
 41.6008 +                                temp2=flags&C_FLAG;
 41.6009 +                                while (c>0)
 41.6010 +                                {
 41.6011 +                                        tempc=(temp2)?0x80:0;
 41.6012 +                                        temp2=temp&1;
 41.6013 +                                        temp=(temp>>1)|tempc;
 41.6014 +                                        c--;
 41.6015 +                                        if (is486) cycles--;
 41.6016 +                                }
 41.6017 +                                seteab(temp);   if (abrt) break;
 41.6018 +                                flags&=~(C_FLAG|V_FLAG);
 41.6019 +                                if (temp2) flags|=C_FLAG;
 41.6020 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.6021 +                                cycles-=((mod==3)?9:10);
 41.6022 +                                break;
 41.6023 +                                case 0x20: case 0x30: /*SHL b,CL*/
 41.6024 +                                seteab(temp<<c);        if (abrt) break;
 41.6025 +                                setznp8(temp<<c);
 41.6026 +                                if ((temp<<(c-1))&0x80) flags|=C_FLAG;
 41.6027 +                                if (((temp<<c)^(temp<<(c-1)))&0x80) flags|=V_FLAG;
 41.6028 +                                cycles-=((mod==3)?3:7);
 41.6029 +                                break;
 41.6030 +                                case 0x28: /*SHR b,CL*/
 41.6031 +                                seteab(temp>>c);        if (abrt) break;
 41.6032 +                                setznp8(temp>>c);
 41.6033 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
 41.6034 +                                if (c==1 && temp&0x80) flags|=V_FLAG;
 41.6035 +                                cycles-=((mod==3)?3:7);
 41.6036 +                                break;
 41.6037 +                                case 0x38: /*SAR b,CL*/
 41.6038 +                                tempc=((temp>>(c-1))&1);
 41.6039 +                                while (c>0)
 41.6040 +                                {
 41.6041 +                                        temp>>=1;
 41.6042 +                                        if (temp&0x40) temp|=0x80;
 41.6043 +                                        c--;
 41.6044 +                                }
 41.6045 +                                seteab(temp);   if (abrt) break;
 41.6046 +                                setznp8(temp);
 41.6047 +                                if (tempc) flags|=C_FLAG;
 41.6048 +                                cycles-=((mod==3)?3:7);
 41.6049 +                                break;
 41.6050 +                        }
 41.6051 +                        break;
 41.6052 +
 41.6053 +                        case 0xC1: case 0x2C1:
 41.6054 +                        fetchea();
 41.6055 +                        c=readmemb(cs,pc)&31; pc++;
 41.6056 +                        tempw=geteaw();         if (abrt) break;
 41.6057 +                        if (!c) break;
 41.6058 +                        switch (rmdat&0x38)
 41.6059 +                        {
 41.6060 +                                case 0x00: /*ROL w,CL*/
 41.6061 +                                while (c>0)
 41.6062 +                                {
 41.6063 +                                        temp=(tempw&0x8000)?1:0;
 41.6064 +                                        tempw=(tempw<<1)|temp;
 41.6065 +                                        c--;
 41.6066 +                                }
 41.6067 +                                seteaw(tempw);  if (abrt) break;
 41.6068 +                                flags&=~(C_FLAG|V_FLAG);
 41.6069 +                                if (temp) flags|=C_FLAG;
 41.6070 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.6071 +                                cycles-=((mod==3)?3:7);
 41.6072 +                                break;
 41.6073 +                                case 0x08: /*ROR w,CL*/
 41.6074 +                                while (c>0)
 41.6075 +                                {
 41.6076 +                                        tempw2=(tempw&1)?0x8000:0;
 41.6077 +                                        tempw=(tempw>>1)|tempw2;
 41.6078 +                                        c--;
 41.6079 +                                }
 41.6080 +                                seteaw(tempw);  if (abrt) break;
 41.6081 +                                flags&=~(C_FLAG|V_FLAG);
 41.6082 +                                if (tempw2) flags|=C_FLAG;
 41.6083 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.6084 +                                cycles-=((mod==3)?3:7);
 41.6085 +                                break;
 41.6086 +                                case 0x10: /*RCL w,CL*/
 41.6087 +                                temp2=flags&C_FLAG;
 41.6088 +                                while (c>0)
 41.6089 +                                {
 41.6090 +                                        tempc=(temp2)?1:0;
 41.6091 +                                        temp2=(tempw>>15);
 41.6092 +                                        tempw=(tempw<<1)|tempc;
 41.6093 +                                        c--;
 41.6094 +                                        if (is486) cycles--;
 41.6095 +                                }
 41.6096 +                                seteaw(tempw);  if (abrt) break;
 41.6097 +                                flags&=~(C_FLAG|V_FLAG);
 41.6098 +                                if (temp2) flags|=C_FLAG;
 41.6099 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.6100 +                                cycles-=((mod==3)?9:10);
 41.6101 +                                break;
 41.6102 +                                case 0x18: /*RCR w,CL*/
 41.6103 +                                temp2=flags&C_FLAG;
 41.6104 +                                while (c>0)
 41.6105 +                                {
 41.6106 +                                        tempc=(temp2)?0x8000:0;
 41.6107 +                                        temp2=tempw&1;
 41.6108 +                                        tempw=(tempw>>1)|tempc;
 41.6109 +                                        c--;
 41.6110 +                                        if (is486) cycles--;
 41.6111 +                                }
 41.6112 +                                seteaw(tempw);  if (abrt) break;
 41.6113 +                                flags&=~(C_FLAG|V_FLAG);
 41.6114 +                                if (temp2) flags|=C_FLAG;
 41.6115 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.6116 +                                cycles-=((mod==3)?9:10);
 41.6117 +                                break;
 41.6118 +
 41.6119 +                                case 0x20: case 0x30: /*SHL w,CL*/
 41.6120 +                                seteaw(tempw<<c); if (abrt) break;
 41.6121 +                                setznp16(tempw<<c);
 41.6122 +                                if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
 41.6123 +                                if (((tempw<<c)^(tempw<<(c-1)))&0x8000) flags|=V_FLAG;
 41.6124 +                                cycles-=((mod==3)?3:7);
 41.6125 +                                break;
 41.6126 +
 41.6127 +                                case 0x28:            /*SHR w,CL*/
 41.6128 +                                seteaw(tempw>>c); if (abrt) break;
 41.6129 +                                setznp16(tempw>>c);
 41.6130 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
 41.6131 +                                if (c==1 && tempw&0x8000) flags|=V_FLAG;
 41.6132 +                                cycles-=((mod==3)?3:7);
 41.6133 +                                break;
 41.6134 +
 41.6135 +                                case 0x38:            /*SAR w,CL*/
 41.6136 +                                tempw2=tempw&0x8000;
 41.6137 +                                tempc=(tempw>>(c-1))&1;
 41.6138 +                                while (c>0)
 41.6139 +                                {
 41.6140 +                                        tempw=(tempw>>1)|tempw2;
 41.6141 +                                        c--;
 41.6142 +                                }
 41.6143 +                                seteaw(tempw);  if (abrt) break;
 41.6144 +                                setznp16(tempw);
 41.6145 +                                if (tempc) flags|=C_FLAG;
 41.6146 +                                cycles-=((mod==3)?3:7);
 41.6147 +                                break;
 41.6148 +                        }
 41.6149 +                        break;
 41.6150 +                        case 0x1C1: case 0x3C1:
 41.6151 +                        fetchea();
 41.6152 +                        c=readmemb(cs,pc); pc++;
 41.6153 +                        c&=31;
 41.6154 +                        templ=geteal();         if (abrt) break;
 41.6155 +                        if (!c) break;
 41.6156 +                        switch (rmdat&0x38)
 41.6157 +                        {
 41.6158 +                                case 0x00: /*ROL l,CL*/
 41.6159 +                                while (c>0)
 41.6160 +                                {
 41.6161 +                                        temp=(templ&0x80000000)?1:0;
 41.6162 +                                        templ=(templ<<1)|temp;
 41.6163 +                                        c--;
 41.6164 +                                }
 41.6165 +                                seteal(templ);  if (abrt) break;
 41.6166 +                                flags&=~(C_FLAG|V_FLAG);
 41.6167 +                                if (temp) flags|=C_FLAG;
 41.6168 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.6169 +                                cycles-=((mod==3)?9:10);
 41.6170 +                                break;
 41.6171 +                                case 0x08: /*ROR l,CL*/
 41.6172 +                                while (c>0)
 41.6173 +                                {
 41.6174 +                                        templ2=(templ&1)?0x80000000:0;
 41.6175 +                                        templ=(templ>>1)|templ2;
 41.6176 +                                        c--;
 41.6177 +                                }
 41.6178 +                                seteal(templ);  if (abrt) break;
 41.6179 +                                flags&=~(C_FLAG|V_FLAG);
 41.6180 +                                if (templ2) flags|=C_FLAG;
 41.6181 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.6182 +                                cycles-=((mod==3)?9:10);
 41.6183 +                                break;
 41.6184 +                                case 0x10: /*RCL l,CL*/
 41.6185 +                                temp2=flags&C_FLAG;
 41.6186 +                                while (c>0)
 41.6187 +                                {
 41.6188 +                                        tempc=(flags&C_FLAG)?1:0;
 41.6189 +                                        temp2=templ>>31;
 41.6190 +                                        templ=(templ<<1)|tempc;
 41.6191 +                                        c--;
 41.6192 +                                        if (is486) cycles--;
 41.6193 +                                }
 41.6194 +                                seteal(templ);  if (abrt) break;
 41.6195 +                                flags&=~(C_FLAG|V_FLAG);
 41.6196 +                                if (temp2) flags|=C_FLAG;
 41.6197 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.6198 +                                cycles-=((mod==3)?9:10);
 41.6199 +                                break;
 41.6200 +                                case 0x18: /*RCR l,CL*/
 41.6201 +                                temp2=flags&C_FLAG;
 41.6202 +                                while (c>0)
 41.6203 +                                {
 41.6204 +                                        tempc=(temp2)?0x80000000:0;
 41.6205 +                                        temp2=templ&1;
 41.6206 +                                        templ=(templ>>1)|tempc;
 41.6207 +                                        c--;
 41.6208 +                                        if (is486) cycles--;
 41.6209 +                                }
 41.6210 +                                seteal(templ);  if (abrt) break;
 41.6211 +                                flags&=~(C_FLAG|V_FLAG);
 41.6212 +                                if (temp2) flags|=C_FLAG;
 41.6213 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.6214 +                                cycles-=((mod==3)?9:10);
 41.6215 +                                break;
 41.6216 +
 41.6217 +                                case 0x20: case 0x30: /*SHL l,CL*/
 41.6218 +                                seteal(templ<<c); if (abrt) break;
 41.6219 +                                setznp32(templ<<c);
 41.6220 +                                if ((templ<<(c-1))&0x80000000) flags|=C_FLAG;
 41.6221 +                                if (((templ<<c)^(templ<<(c-1)))&0x80000000) flags|=V_FLAG;
 41.6222 +                                cycles-=((mod==3)?3:7);
 41.6223 +                                break;
 41.6224 +
 41.6225 +                                case 0x28:            /*SHR l,CL*/
 41.6226 +                                seteal(templ>>c);       if (abrt) break;
 41.6227 +                                setznp32(templ>>c);
 41.6228 +                                if ((templ>>(c-1))&1) flags|=C_FLAG;
 41.6229 +                                if (c==1 && templ&0x80000000) flags|=V_FLAG;
 41.6230 +                                cycles-=((mod==3)?3:7);
 41.6231 +                                break;
 41.6232 +
 41.6233 +                                case 0x38:            /*SAR l,CL*/
 41.6234 +                                templ2=templ&0x80000000;
 41.6235 +                                tempc=(templ>>(c-1))&1;
 41.6236 +                                while (c>0)
 41.6237 +                                {
 41.6238 +                                        templ=(templ>>1)|templ2;
 41.6239 +                                        c--;
 41.6240 +                                }
 41.6241 +                                seteal(templ);  if (abrt) break;
 41.6242 +                                setznp32(templ);
 41.6243 +                                if (tempc) flags|=C_FLAG;
 41.6244 +                                cycles-=((mod==3)?3:7);
 41.6245 +                                break;
 41.6246 +                        }
 41.6247 +                        break;
 41.6248 +
 41.6249 +
 41.6250 +                        case 0xC2: case 0x2C2: /*RET*/
 41.6251 +                        tempw=getword();
 41.6252 +                        if (ssegs) ss=oldss;
 41.6253 +                        if (stack32)
 41.6254 +                        {
 41.6255 +                                tempw2=readmemw(ss,ESP); if (abrt) break;
 41.6256 +                                ESP+=2+tempw;
 41.6257 +                        }
 41.6258 +                        else
 41.6259 +                        {
 41.6260 +                                tempw2=readmemw(ss,SP); if (abrt) break;
 41.6261 +                                SP+=2+tempw;
 41.6262 +                        }
 41.6263 +                        pc=tempw2;
 41.6264 +                        cycles-=(is486)?5:10;
 41.6265 +                        break;
 41.6266 +                        case 0x1C2: case 0x3C2: /*RET*/
 41.6267 +                        tempw=getword();
 41.6268 +                        if (ssegs) ss=oldss;
 41.6269 +                        if (stack32)
 41.6270 +                        {
 41.6271 +                                templ=readmeml(ss,ESP); if (abrt) break;
 41.6272 +                                ESP+=4+tempw;
 41.6273 +                        }
 41.6274 +                        else
 41.6275 +                        {
 41.6276 +                                templ=readmeml(ss,SP);  if (abrt) break;
 41.6277 +                                SP+=4+tempw;
 41.6278 +                        }
 41.6279 +                        pc=templ;
 41.6280 +                        cycles-=(is486)?5:10;
 41.6281 +                        break;
 41.6282 +                        case 0xC3: case 0x2C3: /*RET*/
 41.6283 +                        if (ssegs) ss=oldss;
 41.6284 +                        if (stack32)
 41.6285 +                        {
 41.6286 +                                tempw=readmemw(ss,ESP); if (abrt) break;
 41.6287 +                                ESP+=2;
 41.6288 +                        }
 41.6289 +                        else
 41.6290 +                        {
 41.6291 +                                tempw=readmemw(ss,SP);  if (abrt) break;
 41.6292 +                                SP+=2;
 41.6293 +                        }
 41.6294 +                        pc=tempw;
 41.6295 +                        cycles-=(is486)?5:10;
 41.6296 +                        break;
 41.6297 +                        case 0x1C3: case 0x3C3: /*RET*/
 41.6298 +                        if (ssegs) ss=oldss;
 41.6299 +                        if (stack32)
 41.6300 +                        {
 41.6301 +                                templ=readmeml(ss,ESP); if (abrt) break;
 41.6302 +                                ESP+=4;
 41.6303 +                        }
 41.6304 +                        else
 41.6305 +                        {
 41.6306 +                                templ=readmeml(ss,SP);  if (abrt) break;
 41.6307 +                                SP+=4;
 41.6308 +                        }
 41.6309 +                        pc=templ;
 41.6310 +                        cycles-=(is486)?5:10;
 41.6311 +                        break;
 41.6312 +                        case 0xC4: case 0x2C4: /*LES*/
 41.6313 +                        fetchea();
 41.6314 +                        tempw2=readmemw(easeg,eaaddr);
 41.6315 +                        tempw=readmemw(easeg,eaaddr+2);
 41.6316 +//                        if (output==3) pclog("LES %04X:%08X %04X:%08X\n",easeg,eaaddr,tempw,tempw2);
 41.6317 +                        if (abrt) break;
 41.6318 +                        loadseg(tempw,&_es);
 41.6319 +                        if (abrt) break;
 41.6320 +                        regs[reg].w=tempw2;
 41.6321 +//                        if (output==3) pclog("LES complete\n");
 41.6322 +//                        if (!ES) pclog("LES=0 %04X(%06X):%04X\n",CS,cs,pc);
 41.6323 +//                        if (cr0&1) pclog("ES loaded with %04X  %04X(%08X):%08X\n",tempw,CS,cs,pc);
 41.6324 +                        cycles-=7;
 41.6325 +                        break;
 41.6326 +                        case 0x1C4: case 0x3C4: /*LES*/
 41.6327 +                        fetchea();
 41.6328 +                        templ=readmeml(easeg,eaaddr);
 41.6329 +                        tempw=readmemw(easeg,eaaddr+4);
 41.6330 +                        if (abrt) break;
 41.6331 +                        loadseg(tempw,&_es);
 41.6332 +                        if (abrt) break;
 41.6333 +                        regs[reg].l=templ;
 41.6334 +                        cycles-=7;
 41.6335 +                        break;
 41.6336 +                        case 0xC5: case 0x2C5: /*LDS*/
 41.6337 +                        fetchea();
 41.6338 +                        tempw2=readmemw(easeg,eaaddr);
 41.6339 +                        tempw=readmemw(easeg,eaaddr+2);
 41.6340 +                        if (abrt) break;
 41.6341 +                        loadseg(tempw,&_ds);
 41.6342 +                        if (abrt) break;
 41.6343 +                        if (ssegs) oldds=ds;
 41.6344 +                        regs[reg].w=tempw2;
 41.6345 +                        cycles-=7;
 41.6346 +                        break;
 41.6347 +                        case 0x1C5: case 0x3C5: /*LDS*/
 41.6348 +                        fetchea();
 41.6349 +                        templ=readmeml(easeg,eaaddr);
 41.6350 +                        tempw=readmemw(easeg,eaaddr+4);
 41.6351 +                        if (abrt) break;
 41.6352 +                        loadseg(tempw,&_ds);
 41.6353 +                        if (abrt) break;
 41.6354 +                        if (ssegs) oldds=ds;
 41.6355 +                        regs[reg].l=templ;
 41.6356 +                        cycles-=7;
 41.6357 +                        break;
 41.6358 +                        case 0xC6: case 0x1C6: case 0x2C6: case 0x3C6: /*MOV b,#8*/
 41.6359 +                        fetchea();
 41.6360 +                        temp=readmemb(cs,pc); pc++;     if (abrt) break;
 41.6361 +                        seteab(temp);
 41.6362 +                        cycles -= timing_rr;
 41.6363 +                        break;
 41.6364 +                        case 0xC7: case 0x2C7: /*MOV w,#16*/
 41.6365 +                        fetchea();
 41.6366 +                        tempw=getword();                if (abrt) break;
 41.6367 +                        seteaw(tempw);
 41.6368 +                        cycles -= timing_rr;
 41.6369 +                        break;
 41.6370 +                        case 0x1C7: case 0x3C7: /*MOV l,#32*/
 41.6371 +                        fetchea();
 41.6372 +                        templ=getlong();                if (abrt) break;
 41.6373 +                        seteal(templ);
 41.6374 +                        cycles -= timing_rr;
 41.6375 +                        break;
 41.6376 +                        case 0xC8: case 0x2C8: /*ENTER*/
 41.6377 +                        tempw2=getword();
 41.6378 +                        tempi=readmemb(cs,pc); pc++;
 41.6379 +                        templ=EBP;
 41.6380 +                        if (stack32) { writememw(ss,(ESP-2),BP);         if (abrt) break; ESP-=2; }
 41.6381 +                        else         { writememw(ss,((SP-2)&0xFFFF),BP); if (abrt) break; SP-=2; }
 41.6382 +                        templ2=ESP;
 41.6383 +                        if (tempi>0)
 41.6384 +                        {
 41.6385 +                                while (--tempi)
 41.6386 +                                {
 41.6387 +                                        EBP-=2;
 41.6388 +                                        if (stack32) tempw=readmemw(ss,EBP);
 41.6389 +                                        else         tempw=readmemw(ss,BP);
 41.6390 +                                        if (abrt) { ESP=templ2; EBP=templ; break; }
 41.6391 +                                        if (stack32) { writememw(ss,(ESP-2),tempw);        ESP-=2; }
 41.6392 +                                        else         { writememw(ss,((SP-2)&0xFFFF),tempw); SP-=2; }
 41.6393 +                                        if (abrt) { ESP=templ2; EBP=templ; break; }
 41.6394 +                                        cycles-=(is486)?3:4;
 41.6395 +                                }
 41.6396 +                                if (stack32) { writememw(ss,(ESP-2),templ2);        ESP-=2; }
 41.6397 +                                else         { writememw(ss,((SP-2)&0xFFFF),templ2); SP-=2; }
 41.6398 +                                if (abrt) { ESP=templ2; EBP=templ; break; }
 41.6399 +                                cycles-=(is486)?3:5;
 41.6400 +                        }
 41.6401 +                        BP = templ2;
 41.6402 +                        if (stack32) ESP-=tempw2;
 41.6403 +                        else         SP-=tempw2;
 41.6404 +                        cycles-=(is486)?14:10;
 41.6405 +//                        if (cr0&1) pclog("BP %04X\n",BP);
 41.6406 +//                        if (output==3) pclog("\n");
 41.6407 +                        break;
 41.6408 +                        case 0x1C8: case 0x3C8: /*ENTER*/
 41.6409 +//                        if (output==1 && SS==0xA0)
 41.6410 +//                        {
 41.6411 +//                                enters++;
 41.6412 +//                                for (ec=0;ec<enters;ec++) pclog(" ");
 41.6413 +//                                pclog("ENTER %02X %04X %04X %i\n",SS,BP,SP,eflags&VM_FLAG);
 41.6414 +//                        }
 41.6415 +                        tempw=getword();
 41.6416 +                        tempi=readmemb(cs,pc); pc++;
 41.6417 +                        if (stack32) { writememl(ss,(ESP-4),EBP);         if (abrt) break; ESP-=4; }
 41.6418 +                        else         { writememl(ss,((SP-4)&0xFFFF),EBP); if (abrt) break; SP-=4; }
 41.6419 +                        templ2=ESP; templ3=EBP;
 41.6420 +                        if (tempi>0)
 41.6421 +                        {
 41.6422 +                                while (--tempi)
 41.6423 +                                {
 41.6424 +                                        EBP-=4;
 41.6425 +                                        if (stack32) templ=readmeml(ss,EBP);
 41.6426 +                                        else         templ=readmeml(ss,BP);
 41.6427 +                                        if (abrt) { ESP=templ2; EBP=templ3; break; }
 41.6428 +                                        if (stack32) { writememl(ss,(ESP-4),templ);        ESP-=4; }
 41.6429 +                                        else         { writememl(ss,((SP-4)&0xFFFF),templ); SP-=4; }
 41.6430 +                                        if (abrt) { ESP=templ2; EBP=templ3; break; }
 41.6431 +                                        cycles-=(is486)?3:4;
 41.6432 +                                }
 41.6433 +                                if (stack32) { writememl(ss,(ESP-4),templ2);        ESP-=4; }
 41.6434 +                                else         { writememl(ss,((SP-4)&0xFFFF),templ2); SP-=4; }
 41.6435 +                                if (abrt) { ESP=templ2; EBP=templ3; break; }
 41.6436 +                                cycles-=(is486)?3:5;
 41.6437 +                        }
 41.6438 +                        EBP=templ2;
 41.6439 +                        if (stack32) ESP-=tempw;
 41.6440 +                        else         SP-=tempw;
 41.6441 +                        cycles-=(is486)?14:10;
 41.6442 +//                        if (output==3) pclog("\n");
 41.6443 +                        break;
 41.6444 +                        case 0xC9: case 0x2C9: /*LEAVE*/
 41.6445 +                        templ=ESP;
 41.6446 +                        SP=BP;
 41.6447 +                        if (stack32) { tempw=readmemw(ss,ESP); ESP+=2; }
 41.6448 +                        else         { tempw=readmemw(ss,SP);   SP+=2; }
 41.6449 +                        if (abrt) { ESP=templ; break; }
 41.6450 +                        BP=tempw;
 41.6451 +                        cycles-=4;
 41.6452 +//                        if (output==1 && SS==0xA0)
 41.6453 +//                        {
 41.6454 +//                                for (ec=0;ec<enters;ec++) pclog(" ");
 41.6455 +//                                pclog("LEAVE %02X %04X %04X %i\n",SS,BP,SP,eflags&VM_FLAG);
 41.6456 +//                                enters--;
 41.6457 +//                        }
 41.6458 +//                        if (output==3) pclog("\n");
 41.6459 +                        break;
 41.6460 +                        case 0x3C9: case 0x1C9: /*LEAVE*/
 41.6461 +                        templ=ESP;
 41.6462 +                        ESP=EBP;
 41.6463 +                        if (stack32) { templ2=readmeml(ss,ESP); ESP+=4; }
 41.6464 +                        else         { templ2=readmeml(ss,SP);  SP+=4;  }
 41.6465 +                        if (abrt) { ESP=templ; break; }
 41.6466 +                        EBP=templ2;
 41.6467 +                        cycles-=4;
 41.6468 +//                        if (output==1 && SS==0xA0)
 41.6469 +//                        {
 41.6470 +//                                for (ec=0;ec<enters;ec++) pclog(" ");
 41.6471 +//                                pclog("LEAVE %02X %04X %04X %i\n",SS,BP,SP,eflags&VM_FLAG);
 41.6472 +//                                enters--;
 41.6473 +//                        }
 41.6474 +//                        if (output==3) pclog("\n");
 41.6475 +                        break;
 41.6476 +                        case 0xCA: case 0x2CA: /*RETF*/
 41.6477 +                        tempw=getword();
 41.6478 +                        if ((msw&1) && !(eflags&VM_FLAG))
 41.6479 +                        {
 41.6480 +                                pmoderetf(0,tempw);
 41.6481 +                                break;
 41.6482 +                        }
 41.6483 +                        tempw2=CPL;
 41.6484 +                        if (ssegs) ss=oldss;
 41.6485 +                        oxpc=pc;
 41.6486 +                        if (stack32)
 41.6487 +                        {
 41.6488 +                                pc=readmemw(ss,ESP);
 41.6489 +                                loadcs(readmemw(ss,ESP+2));
 41.6490 +                        }
 41.6491 +                        else
 41.6492 +                        {
 41.6493 +                                pc=readmemw(ss,SP);
 41.6494 +                                loadcs(readmemw(ss,SP+2));
 41.6495 +                        }
 41.6496 +                        if (abrt) break;
 41.6497 +                        if (stack32) ESP+=4+tempw;
 41.6498 +                        else         SP+=4+tempw;
 41.6499 +                        cycles-=(is486)?13:18;
 41.6500 +                        break;
 41.6501 +                        case 0x1CA: case 0x3CA: /*RETF*/
 41.6502 +                        tempw=getword();
 41.6503 +                        if ((msw&1) && !(eflags&VM_FLAG))
 41.6504 +                        {
 41.6505 +                                pmoderetf(1,tempw);
 41.6506 +                                break;
 41.6507 +                        }
 41.6508 +                        tempw2=CPL;
 41.6509 +                        if (ssegs) ss=oldss;
 41.6510 +                        oxpc=pc;
 41.6511 +                        if (stack32)
 41.6512 +                        {
 41.6513 +                                pc=readmeml(ss,ESP);
 41.6514 +                                loadcs(readmeml(ss,ESP+4)&0xFFFF);
 41.6515 +                        }
 41.6516 +                        else
 41.6517 +                        {
 41.6518 +                                pc=readmeml(ss,SP);
 41.6519 +                                loadcs(readmeml(ss,SP+4)&0xFFFF);
 41.6520 +                        }
 41.6521 +                        if (abrt) break;
 41.6522 +                        if (stack32) ESP+=8+tempw;
 41.6523 +                        else         SP+=8+tempw;
 41.6524 +                        cycles-=(is486)?13:18;
 41.6525 +                        break;
 41.6526 +                        case 0xCB: case 0x2CB: /*RETF*/
 41.6527 +                        if ((msw&1) && !(eflags&VM_FLAG))
 41.6528 +                        {
 41.6529 +                                pmoderetf(0,0);
 41.6530 +                                break;
 41.6531 +                        }
 41.6532 +                        tempw2=CPL;
 41.6533 +                        if (ssegs) ss=oldss;
 41.6534 +                        oxpc=pc;
 41.6535 +                        if (stack32)
 41.6536 +                        {
 41.6537 +                                pc=readmemw(ss,ESP);
 41.6538 +                                loadcs(readmemw(ss,ESP+2));
 41.6539 +                        }
 41.6540 +                        else
 41.6541 +                        {
 41.6542 +                                pc=readmemw(ss,SP);
 41.6543 +                                loadcs(readmemw(ss,SP+2));
 41.6544 +                        }
 41.6545 +                        if (abrt) break;
 41.6546 +                        if (stack32) ESP+=4;
 41.6547 +                        else         SP+=4;
 41.6548 +                        cycles-=(is486)?13:18;
 41.6549 +                        break;
 41.6550 +                        case 0x1CB: case 0x3CB: /*RETF*/
 41.6551 +                        if ((msw&1) && !(eflags&VM_FLAG))
 41.6552 +                        {
 41.6553 +                                pmoderetf(1,0);
 41.6554 +                                break;
 41.6555 +                        }
 41.6556 +                        tempw2=CPL;
 41.6557 +                        if (ssegs) ss=oldss;
 41.6558 +                        oxpc=pc;
 41.6559 +                        if (stack32)
 41.6560 +                        {
 41.6561 +                                pc=readmeml(ss,ESP);
 41.6562 +                                loadcs(readmemw(ss,ESP+4));
 41.6563 +                        }
 41.6564 +                        else
 41.6565 +                        {
 41.6566 +                                pc=readmeml(ss,SP);
 41.6567 +                                loadcs(readmemw(ss,SP+4));
 41.6568 +                        }
 41.6569 +                        if (abrt) break;
 41.6570 +                        if (stack32) ESP+=8;
 41.6571 +                        else         SP+=8;
 41.6572 +                        if ((msw&1) && CPL>tempw2)
 41.6573 +                        {
 41.6574 +                                if (stack32)
 41.6575 +                                {
 41.6576 +                                        templ=readmeml(ss,ESP);
 41.6577 +                                        loadseg(readmeml(ss,ESP+4),&_ss);
 41.6578 +                                        ESP=templ;
 41.6579 +                                }
 41.6580 +                                else
 41.6581 +                                {
 41.6582 +                                        templ=readmeml(ss,SP);
 41.6583 +                                        loadseg(readmeml(ss,SP+4),&_ss);
 41.6584 +                                        ESP=templ;
 41.6585 +                                }
 41.6586 +                        }
 41.6587 +                        cycles-=(is486)?13:18;
 41.6588 +                        break;
 41.6589 +                        case 0xCC: case 0x1CC: case 0x2CC: case 0x3CC: /*INT 3*/
 41.6590 +                        if (msw&1)
 41.6591 +                        {
 41.6592 +                                pmodeint(3,1);
 41.6593 +                                cycles-=(is486)?44:59;
 41.6594 +                        }
 41.6595 +                        else
 41.6596 +                        {
 41.6597 +                                if (ssegs) ss=oldss;
 41.6598 +                                if (stack32)
 41.6599 +                                {
 41.6600 +                                        writememw(ss,ESP-2,flags);
 41.6601 +                                        writememw(ss,ESP-4,CS);
 41.6602 +                                        writememw(ss,ESP-6,pc);
 41.6603 +                                        ESP-=6;
 41.6604 +                                }
 41.6605 +                                else
 41.6606 +                                {
 41.6607 +                                        writememw(ss,((SP-2)&0xFFFF),flags);
 41.6608 +                                        writememw(ss,((SP-4)&0xFFFF),CS);
 41.6609 +                                        writememw(ss,((SP-6)&0xFFFF),pc);
 41.6610 +                                        SP-=6;
 41.6611 +                                }
 41.6612 +                                addr=3<<2;
 41.6613 +//                                flags&=~I_FLAG;
 41.6614 +                                flags&=~T_FLAG;
 41.6615 +                                oxpc=pc;
 41.6616 +                                pc=readmemw(0,addr);
 41.6617 +                                loadcs(readmemw(0,addr+2));
 41.6618 +                                cycles-=(is486)?26:33;
 41.6619 +                        }
 41.6620 +                        cycles-=23;
 41.6621 +                        break;
 41.6622 +                        case 0xCD: case 0x1CD: case 0x2CD: case 0x3CD: /*INT*/
 41.6623 +                        /*if (msw&1) pclog("INT %i %i %i\n",cr0&1,eflags&VM_FLAG,IOPL);*/
 41.6624 +                        if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
 41.6625 +                        {
 41.6626 +                                x86gpf(NULL,0);
 41.6627 +                                break;
 41.6628 +                        }
 41.6629 +                        lastpc=pc;
 41.6630 +                        lastcs=CS;
 41.6631 +                        temp=readmemb(cs,pc); pc++;
 41.6632 +                        intrt:
 41.6633 +                                
 41.6634 +//                        if (temp == 0x15 && AX == 0xc203) output = 3;
 41.6635 +//                        /*if (temp == 0x13) */pclog("INT %02X %04X %04X %04X %04X:%04X %04X:%04X %c %i %i\n",temp,AX,BX,CX,DS,DX,CS,pc,(AL>31)?AL:' ', ins, ins2);
 41.6636 +                        if (1)
 41.6637 +                        {
 41.6638 +                                if (msw&1)
 41.6639 +                                {
 41.6640 +//                                        pclog("PMODE int %02X %04X at %04X:%04X  ",temp,AX,CS,pc);
 41.6641 +                                        pmodeint(temp,1);
 41.6642 +                                        cycles-=(is486)?44:59;
 41.6643 +//                                        pclog("to %04X:%04X\n",CS,pc);
 41.6644 +                                }
 41.6645 +                                else
 41.6646 +                                {
 41.6647 +                                        if (ssegs) ss=oldss;
 41.6648 +                                        if (stack32)
 41.6649 +                                        {
 41.6650 +                                                writememw(ss,ESP-2,flags);
 41.6651 +                                                writememw(ss,ESP-4,CS);
 41.6652 +                                                writememw(ss,ESP-6,pc);
 41.6653 +                                                ESP-=6;
 41.6654 +                                        }
 41.6655 +                                        else
 41.6656 +                                        {
 41.6657 +                                                writememw(ss,((SP-2)&0xFFFF),flags);
 41.6658 +                                                writememw(ss,((SP-4)&0xFFFF),CS);
 41.6659 +                                                writememw(ss,((SP-6)&0xFFFF),pc);
 41.6660 +                                                SP-=6;
 41.6661 +                                        }
 41.6662 +                                        addr=temp<<2;
 41.6663 +//                                        flags&=~I_FLAG;
 41.6664 +                                        flags&=~T_FLAG;
 41.6665 +                                        oxpc=pc;
 41.6666 +//                                        pclog("%04X:%04X : ",CS,pc);
 41.6667 +                                        pc=readmemw(0,addr);
 41.6668 +                                        loadcs(readmemw(0,addr+2));
 41.6669 +                                        cycles-=(is486)?30:37;
 41.6670 +//                                        pclog("INT %02X - %04X %04X:%04X\n",temp,addr,CS,pc);
 41.6671 +                                }
 41.6672 +                        }
 41.6673 +                        break;
 41.6674 +                        case 0xCE: /*INTO*/
 41.6675 +                        if (flags&V_FLAG)
 41.6676 +                        {
 41.6677 +                                temp=4;
 41.6678 +                                goto intrt;
 41.6679 +                        }
 41.6680 +                        cycles-=3;
 41.6681 +                        break;
 41.6682 +                        case 0xCF: case 0x2CF: /*IRET*/
 41.6683 +//                        if (CS == 0xc000) output = 0;
 41.6684 +//                        pclog("IRET\n");
 41.6685 +                        if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
 41.6686 +                        {
 41.6687 +                                x86gpf(NULL,0);
 41.6688 +                                break;
 41.6689 +                        }
 41.6690 +//                        output=0;
 41.6691 +                        if (ssegs) ss=oldss;
 41.6692 +                        if (msw&1)
 41.6693 +                        {
 41.6694 +                                optype=IRET;
 41.6695 +                                pmodeiret(0);
 41.6696 +                                optype=0;
 41.6697 +                        }
 41.6698 +                        else
 41.6699 +                        {
 41.6700 +                                tempw=CS;
 41.6701 +                                tempw2=pc;
 41.6702 +                                inint=0;
 41.6703 +                                oxpc=pc;
 41.6704 +                                if (stack32)
 41.6705 +                                {
 41.6706 +                                        pc=readmemw(ss,ESP);
 41.6707 +                                        loadcs(readmemw(ss,ESP+2));
 41.6708 +                                }
 41.6709 +                                else
 41.6710 +                                {
 41.6711 +                                        pc=readmemw(ss,SP);
 41.6712 +                                        loadcs(readmemw(ss,((SP+2)&0xFFFF)));
 41.6713 +                                }
 41.6714 +                                if (stack32)
 41.6715 +                                {
 41.6716 +                                        flags=(readmemw(ss,ESP+4)&0xFFD5)|2;
 41.6717 +                                        ESP+=6;
 41.6718 +                                }
 41.6719 +                                else
 41.6720 +                                {
 41.6721 +                                        flags=(readmemw(ss,((SP+4)&0xFFFF))&0xFFD5)|2;
 41.6722 +                                        SP+=6;
 41.6723 +                                }
 41.6724 +                        }
 41.6725 +                        cycles-=(is486)?15:22;
 41.6726 +                        break;
 41.6727 +                        case 0x1CF: case 0x3CF: /*IRETD*/
 41.6728 +//                        if (output==3) output=1;
 41.6729 +//                        pclog("IRET\n");
 41.6730 +                        if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
 41.6731 +                        {
 41.6732 +                                x86gpf(NULL,0);
 41.6733 +                                break;
 41.6734 +                        }
 41.6735 +//                        output=0;
 41.6736 +                        if (ssegs) ss=oldss;
 41.6737 +                        if (msw&1)
 41.6738 +                        {
 41.6739 +                                optype=IRET;
 41.6740 +                                pmodeiret(1);
 41.6741 +                                optype=0;
 41.6742 +                        }
 41.6743 +                        else
 41.6744 +                        {
 41.6745 +                                tempw=CS;
 41.6746 +                                tempw2=pc;
 41.6747 +                                inint=0;
 41.6748 +                                oxpc=pc;
 41.6749 +                                if (stack32)
 41.6750 +                                {
 41.6751 +                                        pc=readmeml(ss,ESP);
 41.6752 +                                        templ=readmeml(ss,ESP+4);
 41.6753 +                                }
 41.6754 +                                else
 41.6755 +                                {
 41.6756 +                                        pc=readmeml(ss,SP);
 41.6757 +                                        templ=readmeml(ss,((SP+4)&0xFFFF));
 41.6758 +                                }
 41.6759 +                                if (stack32)
 41.6760 +                                {
 41.6761 +                                        flags=(readmemw(ss,ESP+8)&0xFFD5)|2;
 41.6762 +                                        eflags=readmemw(ss,ESP+10);
 41.6763 +                                        ESP+=12;
 41.6764 +                                }
 41.6765 +                                else
 41.6766 +                                {
 41.6767 +                                        flags=(readmemw(ss,(SP+8)&0xFFFF)&0xFFD5)|2;
 41.6768 +                                        eflags=readmemw(ss,(SP+10)&0xFFFF);
 41.6769 +                                        SP+=12;
 41.6770 +                                }
 41.6771 +                                loadcs(templ);
 41.6772 +                        }
 41.6773 +                        cycles-=(is486)?15:22;
 41.6774 +                        break;
 41.6775 +                        
 41.6776 +                        case 0xD0: case 0x1D0: case 0x2D0: case 0x3D0:
 41.6777 +                        fetchea();
 41.6778 +                        temp=geteab(); if (abrt) break;
 41.6779 +                        switch (rmdat&0x38)
 41.6780 +                        {
 41.6781 +                                case 0x00: /*ROL b,1*/
 41.6782 +                                seteab((temp<<1)|((temp&0x80)?1:0)); if (abrt) break;
 41.6783 +                                if (temp&0x80) flags|=C_FLAG;
 41.6784 +                                else           flags&=~C_FLAG;
 41.6785 +                                temp<<=1;
 41.6786 +                                if (flags&C_FLAG) temp|=1;
 41.6787 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.6788 +                                else                          flags&=~V_FLAG;
 41.6789 +                                cycles-=((mod==3)?3:7);
 41.6790 +                                break;
 41.6791 +                                case 0x08: /*ROR b,1*/
 41.6792 +                                seteab((temp>>1)|((temp&1)?0x80:0)); if (abrt) break;
 41.6793 +                                if (temp&1) flags|=C_FLAG;
 41.6794 +                                else        flags&=~C_FLAG;
 41.6795 +                                temp>>=1;
 41.6796 +                                if (flags&C_FLAG) temp|=0x80;
 41.6797 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.6798 +                                else                       flags&=~V_FLAG;
 41.6799 +                                cycles-=((mod==3)?3:7);
 41.6800 +                                break;
 41.6801 +                                case 0x10: /*RCL b,1*/
 41.6802 +                                temp2=flags&C_FLAG;
 41.6803 +                                seteab((temp<<1)|temp2); if (abrt) break;
 41.6804 +                                if (temp&0x80) flags|=C_FLAG;
 41.6805 +                                else           flags&=~C_FLAG;
 41.6806 +                                temp<<=1;
 41.6807 +                                if (temp2) temp|=1;
 41.6808 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.6809 +                                else                          flags&=~V_FLAG;
 41.6810 +                                cycles-=((mod==3)?3:7);
 41.6811 +                                break;
 41.6812 +                                case 0x18: /*RCR b,1*/
 41.6813 +                                temp2=flags&C_FLAG;
 41.6814 +                                seteab((temp>>1)|(temp2?0x80:0)); if (abrt) break;
 41.6815 +                                if (temp&1) flags|=C_FLAG;
 41.6816 +                                else        flags&=~C_FLAG;
 41.6817 +                                temp>>=1;
 41.6818 +                                if (temp2) temp|=0x80;
 41.6819 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.6820 +                                else                       flags&=~V_FLAG;
 41.6821 +                                cycles-=((mod==3)?3:7);
 41.6822 +                                break;
 41.6823 +                                case 0x20: case 0x30: /*SHL b,1*/
 41.6824 +                                seteab(temp<<1); if (abrt) break;
 41.6825 +                                setznp8(temp<<1);
 41.6826 +                                if (temp&0x80) flags|=C_FLAG;
 41.6827 +                                if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
 41.6828 +                                cycles-=((mod==3)?3:7);
 41.6829 +                                break;
 41.6830 +                                case 0x28: /*SHR b,1*/
 41.6831 +                                seteab(temp>>1); if (abrt) break;
 41.6832 +                                setznp8(temp>>1);
 41.6833 +                                if (temp&1) flags|=C_FLAG;
 41.6834 +                                if (temp&0x80) flags|=V_FLAG;
 41.6835 +                                cycles-=((mod==3)?3:7);
 41.6836 +                                break;
 41.6837 +                                case 0x38: /*SAR b,1*/
 41.6838 +                                seteab((temp>>1)|(temp&0x80)); if (abrt) break;
 41.6839 +                                setznp8((temp>>1)|(temp&0x80));
 41.6840 +                                if (temp&1) flags|=C_FLAG;
 41.6841 +                                cycles-=((mod==3)?3:7);
 41.6842 +                                break;
 41.6843 +                        }
 41.6844 +                        break;
 41.6845 +                        case 0xD1: case 0x2D1:
 41.6846 +                        fetchea();
 41.6847 +                        tempw=geteaw(); if (abrt) break;
 41.6848 +                        switch (rmdat&0x38)
 41.6849 +                        {
 41.6850 +                                case 0x00: /*ROL w,1*/
 41.6851 +                                seteaw((tempw<<1)|(tempw>>15)); if (abrt) break;
 41.6852 +                                if (tempw&0x8000) flags|=C_FLAG;
 41.6853 +                                else              flags&=~C_FLAG;
 41.6854 +                                tempw<<=1;
 41.6855 +                                if (flags&C_FLAG) tempw|=1;
 41.6856 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.6857 +                                else                            flags&=~V_FLAG;
 41.6858 +                                cycles-=((mod==3)?3:7);
 41.6859 +                                break;
 41.6860 +                                case 0x08: /*ROR w,1*/
 41.6861 +                                seteaw((tempw>>1)|(tempw<<15)); if (abrt) break;
 41.6862 +                                if (tempw&1) flags|=C_FLAG;
 41.6863 +                                else         flags&=~C_FLAG;
 41.6864 +                                tempw>>=1;
 41.6865 +                                if (flags&C_FLAG) tempw|=0x8000;
 41.6866 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.6867 +                                else                           flags&=~V_FLAG;
 41.6868 +                                cycles-=((mod==3)?3:7);
 41.6869 +                                break;
 41.6870 +                                case 0x10: /*RCL w,1*/
 41.6871 +                                temp2=flags&C_FLAG;
 41.6872 +                                seteaw((tempw<<1)|temp2);       if (abrt) break;
 41.6873 +                                if (tempw&0x8000) flags|=C_FLAG;
 41.6874 +                                else              flags&=~C_FLAG;
 41.6875 +                                tempw<<=1;
 41.6876 +                                if (temp2) tempw|=1;
 41.6877 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.6878 +                                else                            flags&=~V_FLAG;
 41.6879 +                                cycles-=((mod==3)?3:7);
 41.6880 +                                break;
 41.6881 +                                case 0x18: /*RCR w,1*/
 41.6882 +                                temp2=flags&C_FLAG;
 41.6883 +                                seteaw((tempw>>1)|(temp2?0x8000:0));      if (abrt) break;
 41.6884 +                                if (tempw&1) flags|=C_FLAG;
 41.6885 +                                else         flags&=~C_FLAG;
 41.6886 +                                tempw>>=1;
 41.6887 +                                if (temp2) tempw|=0x8000;
 41.6888 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.6889 +                                else                           flags&=~V_FLAG;
 41.6890 +                                cycles-=((mod==3)?3:7);
 41.6891 +                                break;
 41.6892 +                                case 0x20: case 0x30: /*SHL w,1*/
 41.6893 +                                seteaw(tempw<<1);       if (abrt) break;
 41.6894 +                                setznp16(tempw<<1);
 41.6895 +                                if (tempw&0x8000) flags|=C_FLAG;
 41.6896 +                                if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
 41.6897 +                                cycles-=((mod==3)?3:7);
 41.6898 +                                break;
 41.6899 +                                case 0x28: /*SHR w,1*/
 41.6900 +                                seteaw(tempw>>1);       if (abrt) break;
 41.6901 +                                setznp16(tempw>>1);
 41.6902 +                                if (tempw&1) flags|=C_FLAG;
 41.6903 +                                if (tempw&0x8000) flags|=V_FLAG;
 41.6904 +                                cycles-=((mod==3)?3:7);
 41.6905 +                                break;
 41.6906 +                                case 0x38: /*SAR w,1*/
 41.6907 +                                seteaw((tempw>>1)|(tempw&0x8000)); if (abrt) break;
 41.6908 +                                setznp16((tempw>>1)|(tempw&0x8000));
 41.6909 +                                if (tempw&1) flags|=C_FLAG;
 41.6910 +                                cycles-=((mod==3)?3:7);
 41.6911 +                                break;
 41.6912 +
 41.6913 +                                default:
 41.6914 +                                pclog("Bad D1 opcode %02X\n",rmdat&0x38);
 41.6915 +                        }
 41.6916 +                        break;
 41.6917 +                        case 0x1D1: case 0x3D1:
 41.6918 +                        fetchea();
 41.6919 +                        templ=geteal();         if (abrt) break;
 41.6920 +                        switch (rmdat&0x38)
 41.6921 +                        {
 41.6922 +                                case 0x00: /*ROL l,1*/
 41.6923 +                                seteal((templ<<1)|(templ>>31)); if (abrt) break;
 41.6924 +                                if (templ&0x80000000) flags|=C_FLAG;
 41.6925 +                                else                  flags&=~C_FLAG;
 41.6926 +                                templ<<=1;
 41.6927 +                                if (flags&C_FLAG) templ|=1;
 41.6928 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.6929 +                                else                            flags&=~V_FLAG;
 41.6930 +                                cycles-=((mod==3)?3:7);
 41.6931 +                                break;
 41.6932 +                                case 0x08: /*ROR l,1*/
 41.6933 +                                seteal((templ>>1)|(templ<<31)); if (abrt) break;
 41.6934 +                                if (templ&1) flags|=C_FLAG;
 41.6935 +                                else         flags&=~C_FLAG;
 41.6936 +                                templ>>=1;
 41.6937 +                                if (flags&C_FLAG) templ|=0x80000000;
 41.6938 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.6939 +                                else                               flags&=~V_FLAG;
 41.6940 +                                cycles-=((mod==3)?3:7);
 41.6941 +                                break;
 41.6942 +                                case 0x10: /*RCL l,1*/
 41.6943 +                                temp2=flags&C_FLAG;
 41.6944 +                                seteal((templ<<1)|temp2);       if (abrt) break;
 41.6945 +                                if (templ&0x80000000) flags|=C_FLAG;
 41.6946 +                                else                  flags&=~C_FLAG;
 41.6947 +                                templ<<=1;
 41.6948 +                                if (temp2) templ|=1;
 41.6949 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.6950 +                                else                            flags&=~V_FLAG;
 41.6951 +                                cycles-=((mod==3)?3:7);
 41.6952 +                                break;
 41.6953 +                                case 0x18: /*RCR l,1*/
 41.6954 +                                temp2=flags&C_FLAG;
 41.6955 +                                seteal((templ>>1)|(temp2?0x80000000:0)); if (abrt) break;
 41.6956 +                                temp2=flags&C_FLAG;
 41.6957 +                                if (templ&1) flags|=C_FLAG;
 41.6958 +                                else         flags&=~C_FLAG;
 41.6959 +                                templ>>=1;
 41.6960 +                                if (temp2) templ|=0x80000000;
 41.6961 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.6962 +                                else                               flags&=~V_FLAG;
 41.6963 +                                cycles-=((mod==3)?3:7);
 41.6964 +                                break;
 41.6965 +                                case 0x20: case 0x30: /*SHL l,1*/
 41.6966 +                                seteal(templ<<1); if (abrt) break;
 41.6967 +                                setznp32(templ<<1);
 41.6968 +                                if (templ&0x80000000) flags|=C_FLAG;
 41.6969 +                                if ((templ^(templ<<1))&0x80000000) flags|=V_FLAG;
 41.6970 +                                cycles-=((mod==3)?3:7);
 41.6971 +                                break;
 41.6972 +                                case 0x28: /*SHR l,1*/
 41.6973 +                                seteal(templ>>1); if (abrt) break;
 41.6974 +                                setznp32(templ>>1);
 41.6975 +                                if (templ&1) flags|=C_FLAG;
 41.6976 +                                if (templ&0x80000000) flags|=V_FLAG;
 41.6977 +                                cycles-=((mod==3)?3:7);
 41.6978 +                                break;
 41.6979 +                                case 0x38: /*SAR l,1*/
 41.6980 +                                seteal((templ>>1)|(templ&0x80000000)); if (abrt) break;
 41.6981 +                                setznp32((templ>>1)|(templ&0x80000000));
 41.6982 +                                if (templ&1) flags|=C_FLAG;
 41.6983 +                                cycles-=((mod==3)?3:7);
 41.6984 +                                break;
 41.6985 +
 41.6986 +                                default:
 41.6987 +                                pclog("Bad D1 opcode %02X\n",rmdat&0x38);
 41.6988 +                        }
 41.6989 +                        break;
 41.6990 +
 41.6991 +                        case 0xD2: case 0x1D2: case 0x2D2: case 0x3D2:
 41.6992 +                        fetchea();
 41.6993 +                        temp=geteab();  if (abrt) break;
 41.6994 +                        c=CL&31;
 41.6995 +//                        cycles-=c;
 41.6996 +                        if (!c) break;
 41.6997 +//                        if (c>7) pclog("Shiftb %i %02X\n",rmdat&0x38,c);
 41.6998 +                        switch (rmdat&0x38)
 41.6999 +                        {
 41.7000 +                                case 0x00: /*ROL b,CL*/
 41.7001 +                                while (c>0)
 41.7002 +                                {
 41.7003 +                                        temp2=(temp&0x80)?1:0;
 41.7004 +                                        temp=(temp<<1)|temp2;
 41.7005 +                                        c--;
 41.7006 +                                }
 41.7007 +                                seteab(temp); if (abrt) break;
 41.7008 +                                flags&=~(C_FLAG|V_FLAG);
 41.7009 +                                if (temp2) flags|=C_FLAG;
 41.7010 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.7011 +                                cycles-=((mod==3)?3:7);
 41.7012 +                                break;
 41.7013 +                                case 0x08: /*ROR b,CL*/
 41.7014 +                                while (c>0)
 41.7015 +                                {
 41.7016 +                                        temp2=temp&1;
 41.7017 +                                        temp>>=1;
 41.7018 +                                        if (temp2) temp|=0x80;
 41.7019 +                                        c--;
 41.7020 +                                }
 41.7021 +                                seteab(temp); if (abrt) break;
 41.7022 +                                flags&=~(C_FLAG|V_FLAG);
 41.7023 +                                if (temp2) flags|=C_FLAG;
 41.7024 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.7025 +                                cycles-=((mod==3)?3:7);
 41.7026 +                                break;
 41.7027 +                                case 0x10: /*RCL b,CL*/
 41.7028 +                                tempc=flags&C_FLAG;
 41.7029 +                                while (c>0)
 41.7030 +                                {
 41.7031 +                                        templ=tempc;
 41.7032 +                                        tempc=temp&0x80;
 41.7033 +                                        temp<<=1;
 41.7034 +                                        if (templ) temp|=1;
 41.7035 +                                        c--;
 41.7036 +                                }
 41.7037 +                                seteab(temp); if (abrt) break;
 41.7038 +                                flags&=~(C_FLAG|V_FLAG);
 41.7039 +                                if (tempc) flags|=C_FLAG;
 41.7040 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
 41.7041 +                                cycles-=((mod==3)?3:7);
 41.7042 +                                break;
 41.7043 +                                case 0x18: /*RCR b,CL*/
 41.7044 +                                tempc=flags&C_FLAG;
 41.7045 +                                while (c>0)
 41.7046 +                                {
 41.7047 +                                        templ=tempc;
 41.7048 +                                        tempc=temp&1;
 41.7049 +                                        temp>>=1;
 41.7050 +                                        if (templ) temp|=0x80;
 41.7051 +                                        c--;
 41.7052 +                                }
 41.7053 +                                seteab(temp); if (abrt) break;
 41.7054 +                                flags&=~(C_FLAG|V_FLAG);
 41.7055 +                                if (tempc) flags|=C_FLAG;
 41.7056 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
 41.7057 +                                cycles-=((mod==3)?3:7);
 41.7058 +                                break;
 41.7059 +                                case 0x20: case 0x30: /*SHL b,CL*/
 41.7060 +                                seteab(temp<<c); if (abrt) break;
 41.7061 +                                setznp8(temp<<c);
 41.7062 +                                if ((temp<<(c-1))&0x80) flags|=C_FLAG;
 41.7063 +                                if (((temp<<c)^(temp<<(c-1)))&0x80) flags|=V_FLAG;
 41.7064 +                                cycles-=((mod==3)?3:7);
 41.7065 +                                break;
 41.7066 +                                case 0x28: /*SHR b,CL*/
 41.7067 +                                seteab(temp>>c); if (abrt) break;
 41.7068 +                                setznp8(temp>>c);
 41.7069 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
 41.7070 +                                if (c==1 && temp&0x80) flags|=V_FLAG;
 41.7071 +                                cycles-=((mod==3)?3:7);
 41.7072 +                                break;
 41.7073 +                                case 0x38: /*SAR b,CL*/
 41.7074 +                                tempc=(temp>>(c-1))&1;
 41.7075 +                                while (c>0)
 41.7076 +                                {
 41.7077 +                                        temp>>=1;
 41.7078 +                                        if (temp&0x40) temp|=0x80;
 41.7079 +                                        c--;
 41.7080 +                                }
 41.7081 +                                seteab(temp); if (abrt) break;
 41.7082 +                                setznp8(temp);
 41.7083 +                                if (tempc) flags|=C_FLAG;
 41.7084 +                                cycles-=((mod==3)?3:7);
 41.7085 +                                break;
 41.7086 +                        }
 41.7087 +                        break;
 41.7088 +
 41.7089 +                        case 0xD3: case 0x2D3:
 41.7090 +                        fetchea();
 41.7091 +                        tempw=geteaw(); if (abrt) break;
 41.7092 +                        c=CL&31;
 41.7093 +                        if (!c) break;
 41.7094 +                        switch (rmdat&0x38)
 41.7095 +                        {
 41.7096 +                                case 0x00: /*ROL w,CL*/
 41.7097 +                                while (c>0)
 41.7098 +                                {
 41.7099 +                                        temp=(tempw&0x8000)?1:0;
 41.7100 +                                        tempw=(tempw<<1)|temp;
 41.7101 +                                        c--;
 41.7102 +                                }
 41.7103 +                                seteaw(tempw); if (abrt) break;
 41.7104 +                                flags&=~(C_FLAG|V_FLAG);
 41.7105 +                                if (temp) flags|=C_FLAG;
 41.7106 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.7107 +                                cycles-=((mod==3)?3:7);
 41.7108 +                                break;
 41.7109 +                                case 0x08: /*ROR w,CL*/
 41.7110 +                                while (c>0)
 41.7111 +                                {
 41.7112 +                                        tempw2=(tempw&1)?0x8000:0;
 41.7113 +                                        tempw=(tempw>>1)|tempw2;
 41.7114 +                                        c--;
 41.7115 +                                }
 41.7116 +                                seteaw(tempw); if (abrt) break;
 41.7117 +                                flags&=~(C_FLAG|V_FLAG);
 41.7118 +                                if (tempw2) flags|=C_FLAG;
 41.7119 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.7120 +                                cycles-=((mod==3)?3:7);
 41.7121 +                                break;
 41.7122 +                                case 0x10: /*RCL w,CL*/
 41.7123 +                                tempc=flags&C_FLAG;
 41.7124 +                                while (c>0)
 41.7125 +                                {
 41.7126 +                                        templ=tempc;
 41.7127 +                                        tempc=tempw&0x8000;
 41.7128 +                                        tempw=(tempw<<1)|templ;
 41.7129 +                                        c--;
 41.7130 +                                }
 41.7131 +                                seteaw(tempw); if (abrt) break;
 41.7132 +                                flags&=~(C_FLAG|V_FLAG);
 41.7133 +                                if (tempc) flags|=C_FLAG;
 41.7134 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
 41.7135 +                                cycles-=((mod==3)?3:7);
 41.7136 +                                break;
 41.7137 +                                case 0x18: /*RCR w,CL*/
 41.7138 +                                tempc=flags&C_FLAG;
 41.7139 +                                while (c>0)
 41.7140 +                                {
 41.7141 +                                        templ=tempc;
 41.7142 +                                        tempw2=(templ&1)?0x8000:0;
 41.7143 +                                        tempc=tempw&1;
 41.7144 +                                        tempw=(tempw>>1)|tempw2;
 41.7145 +                                        c--;
 41.7146 +                                }
 41.7147 +                                seteaw(tempw); if (abrt) break;
 41.7148 +                                flags&=~(C_FLAG|V_FLAG);
 41.7149 +                                if (tempc) flags|=C_FLAG;
 41.7150 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
 41.7151 +                                cycles-=((mod==3)?3:7);
 41.7152 +                                break;
 41.7153 +
 41.7154 +                                case 0x20: case 0x30: /*SHL w,CL*/
 41.7155 +                                seteaw(tempw<<c); if (abrt) break;
 41.7156 +                                setznp16(tempw<<c);
 41.7157 +                                if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
 41.7158 +                                if (((tempw<<c)^(tempw<<(c-1)))&0x8000) flags|=V_FLAG;
 41.7159 +                                cycles-=((mod==3)?3:7);
 41.7160 +                                break;
 41.7161 +
 41.7162 +                                case 0x28:            /*SHR w,CL*/
 41.7163 +                                seteaw(tempw>>c); if (abrt) break;
 41.7164 +                                setznp16(tempw>>c);
 41.7165 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
 41.7166 +                                if (c==1 && tempw&0x8000) flags|=V_FLAG;
 41.7167 +                                cycles-=((mod==3)?3:7);
 41.7168 +                                break;
 41.7169 +
 41.7170 +                                case 0x38:            /*SAR w,CL*/
 41.7171 +                                tempw2=tempw&0x8000;
 41.7172 +                                tempc=((int16_t)tempw>>(c-1))&1;
 41.7173 +                                while (c>0)
 41.7174 +                                {
 41.7175 +                                        tempw=(tempw>>1)|tempw2;
 41.7176 +                                        c--;
 41.7177 +                                }
 41.7178 +                                seteaw(tempw); if (abrt) break;
 41.7179 +                                setznp16(tempw);
 41.7180 +                                if (tempc) flags|=C_FLAG;
 41.7181 +                                cycles-=((mod==3)?3:7);
 41.7182 +                                break;
 41.7183 +                        }
 41.7184 +                        break;
 41.7185 +                        case 0x1D3: case 0x3D3:
 41.7186 +                        fetchea();
 41.7187 +                        templ=geteal(); if (abrt) break;
 41.7188 +                        c=CL&31;
 41.7189 +                        if (!c) break;
 41.7190 +                        switch (rmdat&0x38)
 41.7191 +                        {
 41.7192 +                                case 0x00: /*ROL l,CL*/
 41.7193 +                                while (c>0)
 41.7194 +                                {
 41.7195 +                                        temp=(templ&0x80000000)?1:0;
 41.7196 +                                        templ=(templ<<1)|temp;
 41.7197 +                                        c--;
 41.7198 +                                }
 41.7199 +                                seteal(templ); if (abrt) break;
 41.7200 +                                flags&=~(C_FLAG|V_FLAG);
 41.7201 +                                if (temp) flags|=C_FLAG;
 41.7202 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.7203 +                                cycles-=((mod==3)?3:7);
 41.7204 +                                break;
 41.7205 +                                case 0x08: /*ROR l,CL*/
 41.7206 +                                while (c>0)
 41.7207 +                                {
 41.7208 +                                        templ2=(templ&1)?0x80000000:0;
 41.7209 +                                        templ=(templ>>1)|templ2;
 41.7210 +                                        c--;
 41.7211 +                                }
 41.7212 +                                seteal(templ); if (abrt) break;
 41.7213 +                                flags&=~(C_FLAG|V_FLAG);
 41.7214 +                                if (templ2) flags|=C_FLAG;
 41.7215 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.7216 +                                cycles-=((mod==3)?3:7);
 41.7217 +                                break;
 41.7218 +                                case 0x10: /*RCL l,CL*/
 41.7219 +                                tempc=flags&C_FLAG;
 41.7220 +                                while (c>0)
 41.7221 +                                {
 41.7222 +                                        templ2=tempc;
 41.7223 +                                        tempc=(templ>>31);
 41.7224 +                                        templ=(templ<<1)|templ2;
 41.7225 +                                        c--;
 41.7226 +                                }
 41.7227 +                                seteal(templ); if (abrt) break;
 41.7228 +                                flags&=~(C_FLAG|V_FLAG);
 41.7229 +                                if (templ2) flags|=C_FLAG;
 41.7230 +                                if ((flags&C_FLAG)^(templ>>31)) flags|=V_FLAG;
 41.7231 +                                cycles-=((mod==3)?3:7);
 41.7232 +                                break;
 41.7233 +                                case 0x18: /*RCR l,CL*/
 41.7234 +                                tempc=flags&C_FLAG;
 41.7235 +                                while (c>0)
 41.7236 +                                {
 41.7237 +                                        templ2=(tempc)?0x80000000:0;
 41.7238 +                                        tempc=templ&1;
 41.7239 +                                        templ=(templ>>1)|templ2;
 41.7240 +                                        c--;
 41.7241 +                                }
 41.7242 +                                seteal(templ); if (abrt) break;
 41.7243 +                                flags&=~(C_FLAG|V_FLAG);
 41.7244 +                                if (templ2) flags|=C_FLAG;
 41.7245 +                                if ((templ^(templ>>1))&0x40000000) flags|=V_FLAG;
 41.7246 +                                cycles-=((mod==3)?3:7);
 41.7247 +                                break;
 41.7248 +
 41.7249 +                                case 0x20: case 0x30: /*SHL l,CL*/
 41.7250 +                                seteal(templ<<c); if (abrt) break;
 41.7251 +                                setznp32(templ<<c);
 41.7252 +                                if ((templ<<(c-1))&0x80000000) flags|=C_FLAG;
 41.7253 +                                if (((templ<<c)^(templ<<(c-1)))&0x80000000) flags|=V_FLAG;
 41.7254 +                                cycles-=((mod==3)?3:7);
 41.7255 +                                break;
 41.7256 +
 41.7257 +                                case 0x28:            /*SHR l,CL*/
 41.7258 +                                seteal(templ>>c); if (abrt) break;
 41.7259 +                                setznp32(templ>>c);
 41.7260 +                                if ((templ>>(c-1))&1) flags|=C_FLAG;
 41.7261 +                                if (c==1 && templ&0x80000000) flags|=V_FLAG;
 41.7262 +                                cycles-=((mod==3)?3:7);
 41.7263 +                                break;
 41.7264 +
 41.7265 +                                case 0x38:            /*SAR w,CL*/
 41.7266 +                                templ2=templ&0x80000000;
 41.7267 +                                tempc=(templ>>(c-1))&1;
 41.7268 +                                while (c>0)
 41.7269 +                                {
 41.7270 +                                        templ=(templ>>1)|templ2;
 41.7271 +                                        c--;
 41.7272 +                                }
 41.7273 +                                seteal(templ); if (abrt) break;
 41.7274 +                                setznp32(templ);
 41.7275 +                                if (tempc) flags|=C_FLAG;
 41.7276 +                                cycles-=((mod==3)?3:7);
 41.7277 +                                break;
 41.7278 +                        }
 41.7279 +                        break;
 41.7280 +
 41.7281 +
 41.7282 +                        case 0xD4: case 0x1D4: case 0x2D4: case 0x3D4: /*AAM*/
 41.7283 +                        tempws=readmemb(cs,pc); pc++;
 41.7284 +                        if (!tempws || cpu_manufacturer != MANU_INTEL) tempws = 10;
 41.7285 +                        AH=AL/tempws;
 41.7286 +                        AL%=tempws;
 41.7287 +                        setznp16(AX);
 41.7288 +                        cycles-=(is486)?15:17;
 41.7289 +                        break;
 41.7290 +                        case 0xD5: case 0x1D5: case 0x2D5: case 0x3D5: /*AAD*/
 41.7291 +                        tempws=readmemb(cs,pc); pc++;
 41.7292 +                        if (cpu_manufacturer != MANU_INTEL) tempws = 10;
 41.7293 +                        AL=(AH*tempws)+AL;
 41.7294 +                        AH=0;
 41.7295 +                        setznp16(AX);
 41.7296 +                        cycles-=(is486)?14:19;
 41.7297 +                        break;
 41.7298 +                        case 0xD6: case 0x1D6: case 0x2D6: case 0x3D6: /*SETALC*/
 41.7299 +                        AL=(flags&C_FLAG)?0xFF:0;
 41.7300 +                        cycles -= timing_rr;
 41.7301 +                        break;
 41.7302 +                        case 0xD7: case 0x1D7: /*XLAT*/
 41.7303 +                        addr=(BX+AL)&0xFFFF;
 41.7304 +                        temp=readmemb(ds,addr); if (abrt) break;
 41.7305 +                        AL=temp;
 41.7306 +                        cycles-=5;
 41.7307 +                        break;
 41.7308 +                        case 0x2D7: case 0x3D7: /*XLAT*/
 41.7309 +                        addr=EBX+AL;
 41.7310 +                        temp=readmemb(ds,addr); if (abrt) break;
 41.7311 +                        AL=temp;
 41.7312 +                        cycles-=5;
 41.7313 +                        break;
 41.7314 +                        case 0xD9: case 0xDA: case 0xDB: case 0xDD:     /*ESCAPE*/
 41.7315 +                        case 0x1D9: case 0x1DA: case 0x1DB: case 0x1DD: /*ESCAPE*/
 41.7316 +                        case 0x2D9: case 0x2DA: case 0x2DB: case 0x2DD: /*ESCAPE*/
 41.7317 +                        case 0x3D9: case 0x3DA: case 0x3DB: case 0x3DD: /*ESCAPE*/
 41.7318 +                        case 0xD8: case 0x1D8: case 0x2D8: case 0x3D8:
 41.7319 +                        case 0xDC: case 0x1DC: case 0x2DC: case 0x3DC:
 41.7320 +                        case 0xDE: case 0x1DE: case 0x2DE: case 0x3DE:
 41.7321 +                        case 0xDF: case 0x1DF: case 0x2DF: case 0x3DF:
 41.7322 +                        if ((cr0&6)==4)
 41.7323 +                        {
 41.7324 +                                pc=oldpc;
 41.7325 +                                pmodeint(7,0);
 41.7326 +                                cycles-=59;
 41.7327 +                        }
 41.7328 +                        else
 41.7329 +                        {
 41.7330 +                                fpucount++;
 41.7331 +                                fetchea();
 41.7332 +                                if (hasfpu)
 41.7333 +                                {
 41.7334 +                                        x87_pc_off=oldpc;
 41.7335 +                                        x87_pc_seg=CS;
 41.7336 +                                        x87_op_off=eaaddr;
 41.7337 +                                        x87_op_seg=ea_rseg;
 41.7338 +                                        switch (opcode)
 41.7339 +                                        {
 41.7340 +                                                case 0xD8: x87_d8(); break;
 41.7341 +                                                case 0xD9: x87_d9(); break;
 41.7342 +                                                case 0xDA: x87_da(); break;
 41.7343 +                                                case 0xDB: x87_db(); break;
 41.7344 +                                                case 0xDC: x87_dc(); break;
 41.7345 +                                                case 0xDD: x87_dd(); break;
 41.7346 +                                                case 0xDE: x87_de(); break;
 41.7347 +                                                case 0xDF: x87_df(); break;
 41.7348 +                                        }
 41.7349 +                                }
 41.7350 +                                //cycles-=8;
 41.7351 +                        }
 41.7352 +                        break;
 41.7353 +
 41.7354 +                        case 0xE0: case 0x1E0: /*LOOPNE*/
 41.7355 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7356 +                        CX--;
 41.7357 +                        if (CX && !(flags&Z_FLAG)) { pc+=offset; }
 41.7358 +                        cycles-=(is486)?7:11;
 41.7359 +                        break;
 41.7360 +                        case 0x2E0: case 0x3E0: /*LOOPNE*/
 41.7361 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7362 +                        ECX--;
 41.7363 +                        if (ECX && !(flags&Z_FLAG)) { pc+=offset; }
 41.7364 +                        cycles-=(is486)?7:11;
 41.7365 +                        break;
 41.7366 +                        case 0xE1: case 0x1E1: /*LOOPE*/
 41.7367 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7368 +                        CX--;
 41.7369 +                        if (CX && (flags&Z_FLAG)) { pc+=offset; }
 41.7370 +                        cycles-=(is486)?7:11;
 41.7371 +                        break;
 41.7372 +                        case 0x2E1: case 0x3E1: /*LOOPE*/
 41.7373 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7374 +                        ECX--;
 41.7375 +                        if (ECX && (flags&Z_FLAG)) { pc+=offset; }
 41.7376 +                        cycles-=(is486)?7:11;
 41.7377 +                        break;
 41.7378 +                        case 0xE2: case 0x1E2: /*LOOP*/
 41.7379 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7380 +                        CX--;
 41.7381 +                        if (CX) { pc+=offset; }
 41.7382 +                        cycles-=(is486)?7:11;
 41.7383 +                        break;
 41.7384 +                        case 0x2E2: case 0x3E2: /*LOOP*/
 41.7385 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7386 +                        ECX--;
 41.7387 +                        if (ECX) { pc+=offset; }
 41.7388 +                        cycles-=(is486)?7:11;
 41.7389 +                        break;
 41.7390 +                        case 0xE3: case 0x1E3: /*JCXZ*/
 41.7391 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7392 +                        if (!CX) { pc+=offset; cycles-=4; }
 41.7393 +                        cycles-=5;
 41.7394 +                        break;
 41.7395 +                        case 0x2E3: case 0x3E3: /*JECXZ*/
 41.7396 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7397 +                        if (!ECX) { pc+=offset; cycles-=4; }
 41.7398 +                        cycles-=5;
 41.7399 +                        break;
 41.7400 +
 41.7401 +                        case 0xE4: case 0x1E4: case 0x2E4: case 0x3E4: /*IN AL*/
 41.7402 +                        temp=readmemb(cs,pc);
 41.7403 +                        checkio_perm(temp);
 41.7404 +                        pc++;
 41.7405 +                        AL=inb(temp);
 41.7406 +                        cycles-=12;
 41.7407 +                        break;
 41.7408 +                        case 0xE5: case 0x2E5: /*IN AX*/
 41.7409 +                        temp=readmemb(cs,pc);
 41.7410 +                        checkio_perm(temp);
 41.7411 +                        checkio_perm(temp+1);
 41.7412 +                        pc++;
 41.7413 +                        AX=inw(temp);
 41.7414 +                        cycles-=12;
 41.7415 +                        break;
 41.7416 +                        case 0x1E5: case 0x3E5: /*IN EAX*/
 41.7417 +                        temp=readmemb(cs,pc);
 41.7418 +                        checkio_perm(temp);
 41.7419 +                        checkio_perm(temp+1);
 41.7420 +                        checkio_perm(temp+2);
 41.7421 +                        checkio_perm(temp+3);
 41.7422 +                        pc++;
 41.7423 +                        EAX=inl(temp);
 41.7424 +                        cycles-=12;
 41.7425 +                        break;
 41.7426 +                        case 0xE6: case 0x1E6: case 0x2E6: case 0x3E6: /*OUT AL*/
 41.7427 +                        temp=readmemb(cs,pc);
 41.7428 +//                        if (output) pclog("OUT %02X,%02X - %08X\n",temp,AL,writelookup2);
 41.7429 +                        checkio_perm(temp);
 41.7430 +  //                      if (output) pclog("              - %08X\n",writelookup2);
 41.7431 +                        pc++;
 41.7432 +                        outb(temp,AL);
 41.7433 +//                        if (output) pclog("              - %08X\n",writelookup2);
 41.7434 +                        cycles-=10;
 41.7435 +                        break;
 41.7436 +                        case 0xE7: case 0x2E7: /*OUT AX*/
 41.7437 +                        temp=readmemb(cs,pc);
 41.7438 +                        checkio_perm(temp);
 41.7439 +                        checkio_perm(temp+1);
 41.7440 +                        pc++;
 41.7441 +                        outw(temp,AX);
 41.7442 +                        cycles-=10;
 41.7443 +                        break;
 41.7444 +                        case 0x1E7: case 0x3E7: /*OUT EAX*/
 41.7445 +                        temp=readmemb(cs,pc);
 41.7446 +                        checkio_perm(temp);
 41.7447 +                        checkio_perm(temp+1);
 41.7448 +                        checkio_perm(temp+2);
 41.7449 +                        checkio_perm(temp+3);
 41.7450 +                        pc++;
 41.7451 +                        outl(temp,EAX);
 41.7452 +                        cycles-=10;
 41.7453 +                        break;
 41.7454 +
 41.7455 +                        case 0xE8: /*CALL rel 16*/
 41.7456 +                        tempw=getword(); if (abrt) break;
 41.7457 +                        if (ssegs) ss=oldss;
 41.7458 +                        if (stack32)
 41.7459 +                        {
 41.7460 +                                writememw(ss,ESP-2,pc); if (abrt) break;
 41.7461 +                                ESP-=2;
 41.7462 +                        }
 41.7463 +                        else
 41.7464 +                        {
 41.7465 +                                writememw(ss,((SP-2)&0xFFFF),pc); if (abrt) break;
 41.7466 +                                SP-=2;
 41.7467 +                        }
 41.7468 +                        pc+=(int16_t)tempw;
 41.7469 +                        cycles-=(is486)?3:7;
 41.7470 +                        break;
 41.7471 +                        case 0x3E8: /*CALL rel 16*/
 41.7472 +                        templ=getlong(); if (abrt) break;
 41.7473 +                        if (ssegs) ss=oldss;
 41.7474 +                        if (stack32)
 41.7475 +                        {
 41.7476 +                                writememl(ss,ESP-4,pc); if (abrt) break;
 41.7477 +                                ESP-=4;
 41.7478 +                        }
 41.7479 +                        else
 41.7480 +                        {
 41.7481 +                                writememl(ss,((SP-4)&0xFFFF),pc); if (abrt) break;
 41.7482 +                                SP-=4;
 41.7483 +                        }
 41.7484 +                        pc+=templ;
 41.7485 +                        cycles-=(is486)?3:7;
 41.7486 +                        break;
 41.7487 +                        case 0xE9: case 0x2E9: /*JMP rel 16*/
 41.7488 +                        tempw=getword(); if (abrt) break;
 41.7489 +                        pc+=(int16_t)tempw;
 41.7490 +                        cycles-=(is486)?3:7;
 41.7491 +                        break;
 41.7492 +                        case 0x1E9: case 0x3E9: /*JMP rel 32*/
 41.7493 +                        templ=getlong(); if (abrt) break;
 41.7494 +                        pc+=templ;
 41.7495 +                        cycles-=(is486)?3:7;
 41.7496 +                        break;
 41.7497 +                        case 0xEA: case 0x2EA: /*JMP far*/
 41.7498 +                        addr=getword();
 41.7499 +                        tempw=getword(); if (abrt) { if (output==3) pclog("JMP ABRT\n"); break; }
 41.7500 +                        oxpc=pc;
 41.7501 +                        pc=addr;
 41.7502 +                        loadcsjmp(tempw,oxpc);
 41.7503 +                        cycles-=(is486)?17:12;
 41.7504 +                        break;
 41.7505 +                        case 0x1EA: case 0x3EA: /*JMP far*/
 41.7506 +                        templ=getlong();
 41.7507 +                        tempw=getword(); if (abrt) break;
 41.7508 +                        oxpc=pc;
 41.7509 +                        pc=templ;
 41.7510 +                        loadcsjmp(tempw,oxpc);
 41.7511 +                        cycles-=(is486)?17:12;
 41.7512 +                        break;
 41.7513 +                        case 0xEB: case 0x1EB: case 0x2EB: case 0x3EB: /*JMP rel*/
 41.7514 +                        offset=(int8_t)readmemb(cs,pc); pc++;
 41.7515 +                        pc+=offset;
 41.7516 +                        cycles-=(is486)?3:7;
 41.7517 +                        break;
 41.7518 +                        case 0xEC: case 0x1EC: case 0x2EC: case 0x3EC: /*IN AL,DX*/
 41.7519 +                        checkio_perm(DX);
 41.7520 +                        AL=inb(DX);
 41.7521 +                        cycles-=13;
 41.7522 +                        break;
 41.7523 +                        case 0xED: case 0x2ED: /*IN AX,DX*/
 41.7524 +                        checkio_perm(DX);
 41.7525 +                        checkio_perm(DX+1);
 41.7526 +                        AX=inw(DX);
 41.7527 +                        cycles-=13;
 41.7528 +                        break;
 41.7529 +                        case 0x1ED: case 0x3ED: /*IN EAX,DX*/
 41.7530 +                        checkio_perm(DX);
 41.7531 +                        checkio_perm(DX+1);
 41.7532 +                        checkio_perm(DX+2);
 41.7533 +                        checkio_perm(DX+3);
 41.7534 +                        EAX=inl(DX);
 41.7535 +                        cycles-=13;
 41.7536 +                        break;
 41.7537 +                        case 0xEE: case 0x1EE: case 0x2EE: case 0x3EE: /*OUT DX,AL*/
 41.7538 +                        checkio_perm(DX);
 41.7539 +                        outb(DX,AL);
 41.7540 +                        cycles-=11;
 41.7541 +                        break;
 41.7542 +                        case 0xEF: case 0x2EF: /*OUT DX,AX*/
 41.7543 +                        checkio_perm(DX);
 41.7544 +                        checkio_perm(DX+1);
 41.7545 +                        outw(DX,AX);
 41.7546 +                        cycles-=11;
 41.7547 +                        break;
 41.7548 +                        case 0x1EF: case 0x3EF: /*OUT DX,EAX*/
 41.7549 +                        checkio_perm(DX);
 41.7550 +                        checkio_perm(DX+1);
 41.7551 +                        checkio_perm(DX+2);
 41.7552 +                        checkio_perm(DX+3);
 41.7553 +                        outl(DX,EAX);
 41.7554 +                        cycles-=11;
 41.7555 +                        break;
 41.7556 +
 41.7557 +                        case 0xF0: case 0x1F0: case 0x2F0: case 0x3F0: /*LOCK*/
 41.7558 +                        cycles-=4;
 41.7559 +                        break;
 41.7560 +
 41.7561 +                        case 0xF2: case 0x1F2: case 0x2F2: case 0x3F2: /*REPNE*/
 41.7562 +                        rep386(0);
 41.7563 +                        break;
 41.7564 +                        case 0xF3: case 0x1F3: case 0x2F3: case 0x3F3: /*REPE*/
 41.7565 +                        rep386(1);
 41.7566 +                        break;
 41.7567 +
 41.7568 +                        case 0xF4: case 0x1F4: case 0x2F4: case 0x3F4: /*HLT*/
 41.7569 +                                if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
 41.7570 +                                {
 41.7571 +//                                        pclog("Can't HLT\n");
 41.7572 +                                        x86gpf(NULL,0);
 41.7573 +                                        //output=3;
 41.7574 +                                        break;
 41.7575 +                                }
 41.7576 +                        inhlt=1;
 41.7577 +                        pc--;
 41.7578 +                        if (!((flags&I_FLAG) && (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)) && !ssegs && !noint)) cycles = oldcyc - 100;
 41.7579 +                        else cycles-=5;
 41.7580 +                        break;
 41.7581 +                        case 0xF5: case 0x1F5: case 0x2F5: case 0x3F5: /*CMC*/
 41.7582 +                        flags^=C_FLAG;
 41.7583 +                        cycles-=2;
 41.7584 +                        break;
 41.7585 +
 41.7586 +                        case 0xF6: case 0x1F6: case 0x2F6: case 0x3F6:
 41.7587 +                        fetchea();
 41.7588 +                        temp=geteab(); if (abrt) break;
 41.7589 +                        switch (rmdat&0x38)
 41.7590 +                        {
 41.7591 +                                case 0x00: /*TEST b,#8*/
 41.7592 +                                temp2=readmemb(cs,pc); pc++; if (abrt) break;
 41.7593 +//                                pclog("TEST %02X,%02X\n",temp,temp2);
 41.7594 +                                temp&=temp2;
 41.7595 +                                setznp8(temp);
 41.7596 +                                if (is486) cycles-=((mod==3)?1:2);
 41.7597 +                                else       cycles-=((mod==3)?2:5);
 41.7598 +                                break;
 41.7599 +                                case 0x10: /*NOT b*/
 41.7600 +                                temp=~temp;
 41.7601 +                                seteab(temp);
 41.7602 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7603 +                                break;
 41.7604 +                                case 0x18: /*NEG b*/
 41.7605 +                                setsub8(0,temp);
 41.7606 +                                temp=0-temp;
 41.7607 +                                seteab(temp);
 41.7608 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7609 +                                break;
 41.7610 +                                case 0x20: /*MUL AL,b*/
 41.7611 +//                                setznp8(AL);
 41.7612 +                                AX=AL*temp;
 41.7613 +//                                if (AX) flags&=~Z_FLAG;
 41.7614 +//                                else    flags|=Z_FLAG;
 41.7615 +                                if (AH) flags|=(C_FLAG|V_FLAG);
 41.7616 +                                else    flags&=~(C_FLAG|V_FLAG);
 41.7617 +                                cycles-=13;
 41.7618 +                                break;
 41.7619 +                                case 0x28: /*IMUL AL,b*/
 41.7620 +//                                setznp8(AL);
 41.7621 +                                tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
 41.7622 +                                AX=tempws&0xFFFF;
 41.7623 +//                                if (AX) flags&=~Z_FLAG;
 41.7624 +//                                else    flags|=Z_FLAG;
 41.7625 +                                if (AH && AH!=0xFF) flags|=(C_FLAG|V_FLAG);
 41.7626 +                                else                flags&=~(C_FLAG|V_FLAG);
 41.7627 +                                cycles-=14;
 41.7628 +                                break;
 41.7629 +                                case 0x30: /*DIV AL,b*/
 41.7630 +                                tempw=AX;
 41.7631 +                                if (temp) tempw2=tempw/temp;
 41.7632 +//                                pclog("DIV %04X/%02X %04X:%04X\n",tempw,temp,CS,pc);
 41.7633 +                                if (temp && !(tempw2&0xFF00))
 41.7634 +                                {
 41.7635 +                                        tempw2=tempw%temp;
 41.7636 +                                        AH=tempw2;
 41.7637 +                                        tempw/=temp;
 41.7638 +                                        AL=tempw&0xFF;
 41.7639 +                                        if (!cpu_iscyrix) flags|=0x8D5; /*Not a Cyrix*/
 41.7640 +                                }
 41.7641 +                                else
 41.7642 +                                {
 41.7643 +//                                        fatal("DIVb BY 0\n");
 41.7644 +                                        pc=oldpc;
 41.7645 +                                        if (msw&1) pmodeint(0,0);
 41.7646 +                                        else
 41.7647 +                                        {
 41.7648 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 41.7649 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 41.7650 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 41.7651 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 41.7652 +                                                SP-=6;
 41.7653 +                                                flags&=~I_FLAG;
 41.7654 +                                                oxpc=pc;
 41.7655 +                                                pc=readmemw(0,0);
 41.7656 +                                                loadcs(readmemw(0,2));
 41.7657 +                                        }
 41.7658 +//                                                cs=loadcs(CS);
 41.7659 +//                                                cs=CS<<4;
 41.7660 +                                }
 41.7661 +                                cycles-=(is486)?16:14;
 41.7662 +                                break;
 41.7663 +                                case 0x38: /*IDIV AL,b*/
 41.7664 +//                                pclog("IDIV %04X/%02X\n",tempw,temp);
 41.7665 +                                tempws=(int)(int16_t)AX;
 41.7666 +                                if (temp!=0) tempws2=tempws/(int)((int8_t)temp);
 41.7667 +                                temps=tempws2&0xFF;
 41.7668 +                                if ((temp!=0) && ((int)temps==tempws2))
 41.7669 +                                {
 41.7670 +                                        tempw2=tempws%(int)((int8_t)temp);
 41.7671 +                                        AH=tempw2&0xFF;
 41.7672 +                                        AL=tempws2&0xFF;
 41.7673 +                                        if (!cpu_iscyrix) flags|=0x8D5; /*Not a Cyrix*/
 41.7674 +                                }
 41.7675 +                                else
 41.7676 +                                {
 41.7677 +                                        pclog("IDIVb exception - %X / %08X = %X\n",tempws,temp,tempws2);
 41.7678 +//                                        pclog("IDIVb BY 0 %04X:%04X\n",cs>>4,pc);
 41.7679 +                                        pc=oldpc;
 41.7680 +                                        if (msw&1) pmodeint(0,0);
 41.7681 +                                        else
 41.7682 +                                        {
 41.7683 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 41.7684 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 41.7685 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 41.7686 +                                                SP-=6;
 41.7687 +                                                flags&=~I_FLAG;
 41.7688 +                                                oxpc=pc;
 41.7689 +                                                pc=readmemw(0,0);
 41.7690 +                                                loadcs(readmemw(0,2));
 41.7691 +                                        }
 41.7692 +//                                                cs=loadcs(CS);
 41.7693 +//                                                cs=CS<<4;
 41.7694 +//                                        pclog("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
 41.7695 +                                }
 41.7696 +                                cycles-=19;
 41.7697 +                                break;
 41.7698 +
 41.7699 +                                default:
 41.7700 +                                pclog("Bad F6 opcode %02X\n",rmdat&0x38);
 41.7701 +                                x86illegal();
 41.7702 +                        }
 41.7703 +                        break;
 41.7704 +
 41.7705 +                        case 0xF7: case 0x2F7:
 41.7706 +                        fetchea();
 41.7707 +                        tempw=geteaw(); if (abrt) break;
 41.7708 +                        switch (rmdat&0x38)
 41.7709 +                        {
 41.7710 +                                case 0x00: /*TEST w*/
 41.7711 +                                tempw2=getword(); if (abrt) break;
 41.7712 +//                                if (output==3) pclog("TEST %04X %04X\n",tempw,tempw2);
 41.7713 +                                setznp16(tempw&tempw2);
 41.7714 +                                if (is486) cycles-=((mod==3)?1:2);
 41.7715 +                                else       cycles-=((mod==3)?2:5);
 41.7716 +                                break;
 41.7717 +                                case 0x10: /*NOT w*/
 41.7718 +                                seteaw(~tempw);
 41.7719 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7720 +                                break;
 41.7721 +                                case 0x18: /*NEG w*/
 41.7722 +                                setsub16(0,tempw);
 41.7723 +                                tempw=0-tempw;
 41.7724 +                                seteaw(tempw);
 41.7725 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7726 +                                break;
 41.7727 +                                case 0x20: /*MUL AX,w*/
 41.7728 +//                                setznp16(AX);
 41.7729 +                                templ=AX*tempw;
 41.7730 +                                AX=templ&0xFFFF;
 41.7731 +                                DX=templ>>16;
 41.7732 +//                                if (AX|DX) flags&=~Z_FLAG;
 41.7733 +//                                else       flags|=Z_FLAG;
 41.7734 +                                if (DX)    flags|=(C_FLAG|V_FLAG);
 41.7735 +                                else       flags&=~(C_FLAG|V_FLAG);
 41.7736 +                                cycles-=21;
 41.7737 +                                break;
 41.7738 +                                case 0x28: /*IMUL AX,w*/
 41.7739 +//                                setznp16(AX);
 41.7740 +//                                pclog("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
 41.7741 +                                templ=(int)((int16_t)AX)*(int)((int16_t)tempw);
 41.7742 +//                                pclog("%i ",tempws);
 41.7743 +                                AX=templ&0xFFFF;
 41.7744 +                                DX=templ>>16;
 41.7745 +                                if (DX && DX!=0xFFFF) flags|=(C_FLAG|V_FLAG);
 41.7746 +                                else                  flags&=~(C_FLAG|V_FLAG);
 41.7747 +                                cycles-=22;
 41.7748 +                                break;
 41.7749 +                                case 0x30: /*DIV AX,w*/
 41.7750 +                                templ=(DX<<16)|AX;
 41.7751 +                                if (tempw) templ2=templ/tempw;
 41.7752 +                                if (tempw && !(templ2&0xFFFF0000))
 41.7753 +                                {
 41.7754 +                                        tempw2=templ%tempw;
 41.7755 +                                        DX=tempw2;
 41.7756 +                                        templ/=tempw;
 41.7757 +                                        AX=templ&0xFFFF;
 41.7758 +                                        if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
 41.7759 +                                }
 41.7760 +                                else
 41.7761 +                                {
 41.7762 +//                                        fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins);
 41.7763 +                                        pc=oldpc;
 41.7764 +                                        if (msw&1) pmodeint(0,0);
 41.7765 +                                        else
 41.7766 +                                        {
 41.7767 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 41.7768 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 41.7769 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 41.7770 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 41.7771 +                                                SP-=6;
 41.7772 +                                                flags&=~I_FLAG;
 41.7773 +                                                oxpc=pc;
 41.7774 +                                                pc=readmemw(0,0);
 41.7775 +                                                loadcs(readmemw(0,2));
 41.7776 +                                        }
 41.7777 +//                                                cs=loadcs(CS);
 41.7778 +//                                                cs=CS<<4;
 41.7779 +//                                        pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x30);
 41.7780 +                                }
 41.7781 +                                cycles-=(is486)?24:22;
 41.7782 +                                break;
 41.7783 +                                case 0x38: /*IDIV AX,w*/
 41.7784 +                                tempws=(int)((DX<<16)|AX);
 41.7785 +                                if (tempw!=0) tempws2=tempws/(int)((int16_t)tempw);
 41.7786 +                                temps16=tempws2&0xFFFF;
 41.7787 +//                                pclog("IDIV %i %i ",tempws,tempw);
 41.7788 +                                if ((tempw!=0) && ((int)temps16==tempws2))
 41.7789 +                                {
 41.7790 +                                        DX=tempws%(int)((int16_t)tempw);
 41.7791 +                                        AX=tempws2&0xFFFF;
 41.7792 +                                        if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
 41.7793 +                                }
 41.7794 +                                else
 41.7795 +                                {
 41.7796 +                                        pclog("IDIVw exception - %X / %08X = %X\n",tempws,tempw,tempws2);
 41.7797 +//                                        pclog("IDIVw BY 0 %04X:%04X\n",cs>>4,pc);
 41.7798 +//                                        DX=0;
 41.7799 +//                                        AX=0xFFFF;
 41.7800 +                                        pc=oldpc;
 41.7801 +                                        if (msw&1) pmodeint(0,0);
 41.7802 +                                        else
 41.7803 +                                        {
 41.7804 +//                                        pclog("%04X:%04X\n",cs>>4,pc);
 41.7805 +                                                writememw(ss,(SP-2)&0xFFFF,flags);
 41.7806 +                                                writememw(ss,(SP-4)&0xFFFF,CS);
 41.7807 +                                                writememw(ss,(SP-6)&0xFFFF,pc);
 41.7808 +                                                SP-=6;
 41.7809 +                                                flags&=~I_FLAG;
 41.7810 +                                                oxpc=pc;
 41.7811 +                                                pc=readmemw(0,0);
 41.7812 +                                                loadcs(readmemw(0,2));
 41.7813 +                                        }
 41.7814 +//                                                cs=loadcs(CS);
 41.7815 +//                                                cs=CS<<4;
 41.7816 +//                                        pclog("Div by zero %04X:%04X %02X %02X 1\n",cs>>4,pc,0xf7,0x38);
 41.7817 +                                }
 41.7818 +                                cycles-=27;
 41.7819 +                                break;
 41.7820 +
 41.7821 +                                default:
 41.7822 +                                pclog("Bad F7 opcode %02X\n",rmdat&0x38);
 41.7823 +                                x86illegal();
 41.7824 +                        }
 41.7825 +                        break;
 41.7826 +                        case 0x1F7: case 0x3F7:
 41.7827 +                        fetchea();
 41.7828 +                        templ=geteal(); if (abrt) break;
 41.7829 +                        switch (rmdat&0x38)
 41.7830 +                        {
 41.7831 +                                case 0x00: /*TEST l*/
 41.7832 +                                templ2=getlong(); if (abrt) break;
 41.7833 +                                setznp32(templ&templ2);
 41.7834 +                                if (is486) cycles-=((mod==3)?1:2);
 41.7835 +                                else       cycles-=((mod==3)?2:5);
 41.7836 +                                break;
 41.7837 +                                case 0x10: /*NOT l*/
 41.7838 +                                seteal(~templ);
 41.7839 +                                cycles -= (mod == 3) ? timing_rr : timing_mml;
 41.7840 +                                break;
 41.7841 +                                case 0x18: /*NEG l*/
 41.7842 +                                setsub32(0,templ);
 41.7843 +                                templ=0-templ;
 41.7844 +                                seteal(templ);
 41.7845 +                                cycles -= (mod == 3) ? timing_rr : timing_mml;
 41.7846 +                                break;
 41.7847 +                                case 0x20: /*MUL EAX,l*/
 41.7848 +                                temp64=(uint64_t)EAX*(uint64_t)templ;
 41.7849 +                                EAX=temp64&0xFFFFFFFF;
 41.7850 +                                EDX=temp64>>32;
 41.7851 +                                if (EDX) flags|= (C_FLAG|V_FLAG);
 41.7852 +                                else     flags&=~(C_FLAG|V_FLAG);
 41.7853 +                                cycles-=21;
 41.7854 +                                break;
 41.7855 +                                case 0x28: /*IMUL EAX,l*/
 41.7856 +                                temp64=(int64_t)(int32_t)EAX*(int64_t)(int32_t)templ;
 41.7857 +                                EAX=temp64&0xFFFFFFFF;
 41.7858 +                                EDX=temp64>>32;
 41.7859 +                                if (EDX && EDX!=0xFFFFFFFF) flags|=(C_FLAG|V_FLAG);
 41.7860 +                                else                        flags&=~(C_FLAG|V_FLAG);
 41.7861 +                                cycles-=38;
 41.7862 +                                break;
 41.7863 +                                case 0x30: /*DIV EAX,l*/
 41.7864 +                                divl(templ);
 41.7865 +                                if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
 41.7866 +                                cycles-=(is486)?40:38;
 41.7867 +                                break;
 41.7868 +                                case 0x38: /*IDIV EAX,l*/
 41.7869 +                                idivl((int32_t)templ);
 41.7870 +                                if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
 41.7871 +                                cycles-=43;
 41.7872 +                                break;
 41.7873 +
 41.7874 +                                default:
 41.7875 +                                pclog("Bad F7 opcode %02X\n",rmdat&0x38);
 41.7876 +                                x86illegal();
 41.7877 +                        }
 41.7878 +                        break;
 41.7879 +
 41.7880 +                        case 0xF8: case 0x1F8: case 0x2F8: case 0x3F8: /*CLC*/
 41.7881 +                        flags&=~C_FLAG;
 41.7882 +                        cycles-=2;
 41.7883 +                        break;
 41.7884 +                        case 0xF9: case 0x1F9: case 0x2F9: case 0x3F9: /*STC*/
 41.7885 +//                        pclog("STC %04X\n",pc);
 41.7886 +                        flags|=C_FLAG;
 41.7887 +                        cycles-=2;
 41.7888 +                        break;
 41.7889 +                        case 0xFA: case 0x1FA: case 0x2FA: case 0x3FA: /*CLI*/
 41.7890 +                        if (!IOPLp)
 41.7891 +                        {
 41.7892 +//                                output=3;
 41.7893 +//                                pclog("Can't CLI %i %i %04X:%08X\n",IOPL,CPL,CS,pc);
 41.7894 +//                                if (CS==0x1C7 && pc==0x5BE) output=3;
 41.7895 +                                x86gpf(NULL,0);
 41.7896 +                        }
 41.7897 +                        else
 41.7898 +                           flags&=~I_FLAG;
 41.7899 +//                        pclog("CLI at %04X:%04X\n",cs>>4,pc);
 41.7900 +                        cycles-=3;
 41.7901 +                        break;
 41.7902 +                        case 0xFB: case 0x1FB: case 0x2FB: case 0x3FB: /*STI*/
 41.7903 +                        if (!IOPLp)
 41.7904 +                        {
 41.7905 +//                                pclog("Can't STI %04X:%08X\n",CS,pc);
 41.7906 +//                                output=3;
 41.7907 +                                x86gpf(NULL,0);
 41.7908 +                        }
 41.7909 +                        else
 41.7910 +                           flags|=I_FLAG;
 41.7911 +//                        pclog("STI at %04X:%04X\n",cs>>4,pc);
 41.7912 +                        cycles-=2;
 41.7913 +                        break;
 41.7914 +                        case 0xFC: case 0x1FC: case 0x2FC: case 0x3FC: /*CLD*/
 41.7915 +                        flags&=~D_FLAG;
 41.7916 +                        cycles-=2;
 41.7917 +                        break;
 41.7918 +                        case 0xFD: case 0x1FD: case 0x2FD: case 0x3FD: /*STD*/
 41.7919 +                        flags|=D_FLAG;
 41.7920 +                        cycles-=2;
 41.7921 +                        break;
 41.7922 +
 41.7923 +                        case 0xFE: case 0x1FE: case 0x2FE: case 0x3FE: /*INC/DEC b*/
 41.7924 +                        fetchea();
 41.7925 +                        temp=geteab(); if (abrt) break;
 41.7926 +                        if (rmdat&0x38)
 41.7927 +                        {
 41.7928 +                                seteab(temp-1); if (abrt) break;
 41.7929 +                                flags&=~V_FLAG;
 41.7930 +                                setsub8nc(temp,1);
 41.7931 +                                temp2=temp-1;
 41.7932 +                                if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
 41.7933 +                        }
 41.7934 +                        else
 41.7935 +                        {
 41.7936 +                                seteab(temp+1); if (abrt) break;
 41.7937 +                                flags&=~V_FLAG;
 41.7938 +                                setadd8nc(temp,1);
 41.7939 +                                temp2=temp+1;
 41.7940 +                                if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
 41.7941 +                        }
 41.7942 +                        cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7943 +                        break;
 41.7944 +
 41.7945 +                        case 0xFF: case 0x2FF:
 41.7946 +                        fetchea();
 41.7947 +                        switch (rmdat&0x38)
 41.7948 +                        {
 41.7949 +                                case 0x00: /*INC w*/
 41.7950 +                                tempw=geteaw();  if (abrt) break;
 41.7951 +                                seteaw(tempw+1); if (abrt) break;
 41.7952 +                                setadd16nc(tempw,1);
 41.7953 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7954 +                                break;
 41.7955 +                                case 0x08: /*DEC w*/
 41.7956 +                                tempw=geteaw();  if (abrt) break;
 41.7957 +                                seteaw(tempw-1); if (abrt) break;
 41.7958 +                                setsub16nc(tempw,1);
 41.7959 +                                cycles -= (mod == 3) ? timing_rr : timing_mm;
 41.7960 +                                break;
 41.7961 +                                case 0x10: /*CALL*/
 41.7962 +                                tempw=geteaw();
 41.7963 +                                if (output) pclog("CALL %04X  %08X:%08X\n", tempw, easeg, eaaddr);
 41.7964 +                                if (abrt) break;
 41.7965 +                                if (ssegs) ss=oldss;
 41.7966 +                                if (stack32)
 41.7967 +                                {
 41.7968 +                                        writememw(ss,ESP-2,pc); if (abrt) break;
 41.7969 +                                        ESP-=2;
 41.7970 +                                }
 41.7971 +                                else
 41.7972 +                                {
 41.7973 +                                        writememw(ss,(SP-2)&0xFFFF,pc); if (abrt) break;
 41.7974 +                                        SP-=2;
 41.7975 +                                }
 41.7976 +                                pc=tempw;
 41.7977 +                                if (is486) cycles-=5;
 41.7978 +                                else       cycles-=((mod==3)?7:10);
 41.7979 +                                break;
 41.7980 +                                case 0x18: /*CALL far*/
 41.7981 +                                tempw=readmemw(easeg,eaaddr);
 41.7982 +                                tempw2=readmemw(easeg,(eaaddr+2)); if (output==3) pclog("CALL FAR %04X:%04X\n",tempw,tempw2); if (abrt) break;
 41.7983 +                                tempw3=CS;
 41.7984 +                                templ2=pc;
 41.7985 +                                if (ssegs) ss=oldss;
 41.7986 +                                oxpc=pc;
 41.7987 +                                pc=tempw;
 41.7988 +                                optype=CALL;
 41.7989 +                                cgate32=0;
 41.7990 +                                if (msw&1) loadcscall(tempw2);
 41.7991 +                                else       loadcs(tempw2);
 41.7992 +                                optype=0;
 41.7993 +                                if (abrt) break;
 41.7994 +                                oldss=ss;
 41.7995 +                                if (cgate32) goto writecall32_2;
 41.7996 +                                writecall16_2:
 41.7997 +                                if (stack32)
 41.7998 +                                {
 41.7999 +                                        writememw(ss,ESP-2,tempw3);
 41.8000 +                                        writememw(ss,ESP-4,templ2);
 41.8001 +                                        ESP-=4;
 41.8002 +                                }
 41.8003 +                                else
 41.8004 +                                {
 41.8005 +                                        writememw(ss,(SP-2)&0xFFFF,tempw3);
 41.8006 +                                        writememw(ss,((SP-4)&0xFFFF),templ2);
 41.8007 +                                        SP-=4;
 41.8008 +                                }
 41.8009 +                                cycles-=(is486)?17:22;
 41.8010 +                                break;
 41.8011 +                                case 0x20: /*JMP*/
 41.8012 +                                tempw=geteaw(); if (abrt) break;
 41.8013 +                                pc=tempw;
 41.8014 +                                if (is486) cycles-=5;
 41.8015 +                                else       cycles-=((mod==3)?7:10);
 41.8016 +                                break;
 41.8017 +                                case 0x28: /*JMP far*/
 41.8018 +                                oxpc=pc;
 41.8019 +                                tempw=readmemw(easeg,eaaddr);
 41.8020 +                                tempw2=readmemw(easeg,eaaddr+2); if (abrt) break;
 41.8021 +                                pc=tempw;                                
 41.8022 +                                loadcsjmp(tempw2,oxpc); if (abrt) break;
 41.8023 +                                cycles-=(is486)?13:12;
 41.8024 +                                break;
 41.8025 +                                case 0x30: /*PUSH w*/
 41.8026 +                                tempw=geteaw(); if (abrt) break;
 41.8027 +                                if (ssegs) ss=oldss;
 41.8028 +                                if (stack32)
 41.8029 +                                {
 41.8030 +                                        writememw(ss,ESP-2,tempw); if (abrt) break;
 41.8031 +                                        ESP-=2;
 41.8032 +                                }
 41.8033 +                                else
 41.8034 +                                {
 41.8035 +//                                        if (output) pclog("PUSH %04X to %04X\n",tempw,SP-2);
 41.8036 +                                        writememw(ss,((SP-2)&0xFFFF),tempw); if (abrt) break;
 41.8037 +                                        SP-=2;
 41.8038 +                                }
 41.8039 +                                cycles-=((mod==3)?2:5);
 41.8040 +                                break;
 41.8041 +
 41.8042 +                                default:
 41.8043 +                                pclog("Bad FF opcode %02X\n",rmdat&0x38);
 41.8044 +                                x86illegal();
 41.8045 +                        }
 41.8046 +                        break;
 41.8047 +                        case 0x1FF: case 0x3FF:
 41.8048 +                        fetchea();
 41.8049 +                        switch (rmdat&0x38)
 41.8050 +                        {
 41.8051 +                                case 0x00: /*INC l*/
 41.8052 +                                templ=geteal();  if (abrt) break;
 41.8053 +                                seteal(templ+1); if (abrt) break;
 41.8054 +                                setadd32nc(templ,1);
 41.8055 +                                cycles -= (mod == 3) ? timing_rr : timing_mml;
 41.8056 +                                break;
 41.8057 +                                case 0x08: /*DEC l*/
 41.8058 +                                templ=geteal();  if (abrt) break;
 41.8059 +                                seteal(templ-1); if (abrt) break;
 41.8060 +                                setsub32nc(templ,1);
 41.8061 +                                cycles -= (mod == 3) ? timing_rr : timing_mml;
 41.8062 +                                break;
 41.8063 +                                case 0x10: /*CALL*/
 41.8064 +                                templ=geteal(); if (abrt) break;
 41.8065 +                                if (ssegs) ss=oldss;
 41.8066 +                                if (stack32)
 41.8067 +                                {
 41.8068 +                                        writememl(ss,ESP-4,pc); if (abrt) break;
 41.8069 +                                        ESP-=4;
 41.8070 +                                }
 41.8071 +                                else
 41.8072 +                                {
 41.8073 +                                        writememl(ss,(SP-4)&0xFFFF,pc); if (abrt) break;
 41.8074 +                                        SP-=4;
 41.8075 +                                }
 41.8076 +                                pc=templ;
 41.8077 +                                if (pc==0xFFFFFFFF) pclog("Failed CALL!\n");
 41.8078 +                                if (is486) cycles-=5;
 41.8079 +                                else       cycles-=((mod==3)?7:10);
 41.8080 +                                break;
 41.8081 +                                case 0x18: /*CALL far*/
 41.8082 +                                templ=readmeml(easeg,eaaddr);
 41.8083 +                                tempw2=readmemw(easeg,(eaaddr+4)); if (abrt) break;
 41.8084 +                                tempw3=CS;
 41.8085 +                                templ2=pc;
 41.8086 +                                if (ssegs) ss=oldss;
 41.8087 +                                oxpc=pc;
 41.8088 +                                pc=templ;
 41.8089 +                                optype=CALL;
 41.8090 +                                cgate16=0;
 41.8091 +                                if (msw&1) loadcscall(tempw2);
 41.8092 +                                else       loadcs(tempw2);
 41.8093 +                                optype=0;
 41.8094 +                                if (abrt) break;
 41.8095 +                                oldss=ss;
 41.8096 +                                if (cgate16) goto writecall16_2;
 41.8097 +                                writecall32_2:
 41.8098 +                                if (stack32)
 41.8099 +                                {
 41.8100 +                                        writememl(ss,ESP-4,tempw3);
 41.8101 +                                        writememl(ss,ESP-8,templ2);
 41.8102 +                                        ESP-=8;
 41.8103 +                                }
 41.8104 +                                else
 41.8105 +                                {
 41.8106 +                                        writememl(ss,(SP-4)&0xFFFF,tempw3);
 41.8107 +                                        writememl(ss,(SP-8)&0xFFFF,templ2);
 41.8108 +                                        SP-=8;
 41.8109 +                                }
 41.8110 +                                if (pc==0xFFFFFFFF) pclog("Failed CALL far!\n");
 41.8111 +                                cycles-=(is486)?17:22;
 41.8112 +                                break;
 41.8113 +                                case 0x20: /*JMP*/
 41.8114 +                                templ=geteal(); if (abrt) break;
 41.8115 +                                pc=templ;
 41.8116 +                                if (is486) cycles-=5;
 41.8117 +                                else       cycles-=((mod==3)?7:12);
 41.8118 +                                if (pc==0xFFFFFFFF) pclog("Failed JMP!\n");
 41.8119 +                                break;
 41.8120 +                                case 0x28: /*JMP far*/
 41.8121 +                                oxpc=pc;
 41.8122 +                                templ=readmeml(easeg,eaaddr);
 41.8123 +                                templ2=readmeml(easeg,eaaddr+4); if (abrt) break;
 41.8124 +                                pc=templ;                                
 41.8125 +                                loadcsjmp(templ2,oxpc);
 41.8126 +                                if (pc==0xFFFFFFFF) pclog("Failed JMP far!\n");
 41.8127 +                                cycles-=(is486)?13:12;
 41.8128 +                                break;
 41.8129 +                                case 0x30: /*PUSH l*/
 41.8130 +                                templ=geteal(); if (abrt) break;
 41.8131 +                                if (ssegs) ss=oldss;
 41.8132 +                                if (stack32)
 41.8133 +                                {
 41.8134 +                                        writememl(ss,ESP-4,templ); if (abrt) break;
 41.8135 +                                        ESP-=4;
 41.8136 +                                }
 41.8137 +                                else
 41.8138 +                                {
 41.8139 +                                        writememl(ss,((SP-4)&0xFFFF),templ); if (abrt) break;
 41.8140 +                                        SP-=4;
 41.8141 +                                }
 41.8142 +                                cycles-=((mod==3)?2:5);
 41.8143 +                                break;
 41.8144 +
 41.8145 +                                default:
 41.8146 +                                pclog("Bad 32-bit FF opcode %02X\n",rmdat&0x38);
 41.8147 +                                x86illegal();
 41.8148 +                        }
 41.8149 +                        break;
 41.8150 +
 41.8151 +                        default:
 41.8152 +//                        pc--;
 41.8153 +//                        cycles-=8;
 41.8154 +//                        break;
 41.8155 +                        pclog("Bad opcode %02X %i %03X at %04X:%04X from %04X:%04X %08X\n",opcode,op32>>8,opcode|op32,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
 41.8156 +                        x86illegal();
 41.8157 +                }
 41.8158 +                opcodeend:
 41.8159 +                if (!use32) pc&=0xFFFF;
 41.8160 +
 41.8161 +                if (ssegs)
 41.8162 +                {
 41.8163 +                        ds=oldds;
 41.8164 +                        ss=oldss;
 41.8165 +                        rds=DS;
 41.8166 +                        ssegs=0;
 41.8167 +                }
 41.8168 +                if (abrt)
 41.8169 +                {
 41.8170 +
 41.8171 +//                        if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
 41.8172 +/*                        if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc);
 41.8173 +                        if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc);
 41.8174 +                        if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc);
 41.8175 +                        if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc);
 41.8176 +                        if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc);
 41.8177 +                        if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc);
 41.8178 +                        if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc);
 41.8179 +                        if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);
 41.8180 +                        if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/
 41.8181 +                        tempi = abrt;
 41.8182 +                        abrt = 0;
 41.8183 +                        x86_doabrt(tempi);
 41.8184 +                        if (abrt)
 41.8185 +                        {
 41.8186 +                                abrt = 0;
 41.8187 +                                CS = oldcs;
 41.8188 +                                pc = oldpc;
 41.8189 +                                pclog("Double fault %i %i\n", ins, resets);
 41.8190 +                                pmodeint(8, 0);
 41.8191 +                                if (abrt)
 41.8192 +                                {
 41.8193 +                                        abrt = 0;
 41.8194 +                                        softresetx86();
 41.8195 +                                        pclog("Triple fault - reset\n");
 41.8196 +                                }
 41.8197 +                        }
 41.8198 +                }
 41.8199 +                cycdiff=oldcyc-cycles;
 41.8200 +
 41.8201 +                if (trap && (flags&T_FLAG) && !noint)
 41.8202 +                {
 41.8203 +//                        oldpc=pc;
 41.8204 +//                        oldcs=CS;
 41.8205 +//                        printf("TRAP!!! %04X:%04X\n",CS,pc);
 41.8206 +                        if (msw&1)
 41.8207 +                        {
 41.8208 +                                pmodeint(1,0);
 41.8209 +                        }
 41.8210 +                        else
 41.8211 +                        {
 41.8212 +                                writememw(ss,(SP-2)&0xFFFF,flags);
 41.8213 +                                writememw(ss,(SP-4)&0xFFFF,CS);
 41.8214 +                                writememw(ss,(SP-6)&0xFFFF,pc);
 41.8215 +                                SP-=6;
 41.8216 +                                addr=1<<2;
 41.8217 +                                flags&=~I_FLAG;
 41.8218 +                                flags&=~T_FLAG;
 41.8219 +                                pc=readmemw(0,addr);
 41.8220 +                                loadcs(readmemw(0,addr+2));
 41.8221 +                        }
 41.8222 +                }
 41.8223 +                else if ((flags&I_FLAG) && (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2)) && !noint)
 41.8224 +                {
 41.8225 +                        temp=picinterrupt();
 41.8226 +                        if (temp!=0xFF)
 41.8227 +                        {
 41.8228 +//                                if (temp == 0x54) pclog("Take int 54\n");
 41.8229 +//                                if (output) output=3;
 41.8230 +//                                pclog("Hardware int %02X %i %i %04X(%08X):%08X\n",temp,ins, ins2, CS,cs,pc);
 41.8231 +//                                if (temp==0x54) output=3;
 41.8232 +                                if (inhlt) pc++;
 41.8233 +                                if (msw&1)
 41.8234 +                                {
 41.8235 +                                        pmodeint(temp,0);
 41.8236 +                                }
 41.8237 +                                else
 41.8238 +                                {
 41.8239 +                                        writememw(ss,(SP-2)&0xFFFF,flags);
 41.8240 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
 41.8241 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
 41.8242 +                                        SP-=6;
 41.8243 +                                        addr=temp<<2;
 41.8244 +                                        flags&=~I_FLAG;
 41.8245 +                                        flags&=~T_FLAG;
 41.8246 +                                        oxpc=pc;
 41.8247 +                                        pc=readmemw(0,addr);
 41.8248 +                                        loadcs(readmemw(0,addr+2));
 41.8249 +//                                        if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
 41.8250 +                                }
 41.8251 +                                inint=1;
 41.8252 +                        }
 41.8253 +                }
 41.8254 +                if (noint) noint=0;
 41.8255 +                ins++;
 41.8256 +                insc++;
 41.8257 +                
 41.8258 +/*                if (times && ins == 9000000) output = 3;
 41.8259 +                if (CS == 0x1000 && pc == 0x1200)
 41.8260 +                   fatal("Hit it\n");*/
 41.8261 +//                if (!ins) ins2++;
 41.8262 +
 41.8263 +                }
 41.8264 +                
 41.8265 +                keybsenddelay -= cycdiff;
 41.8266 +                if (keybsenddelay<1)
 41.8267 +                {
 41.8268 +                        keybsenddelay = 1000;
 41.8269 +                        keyboard_at_poll();
 41.8270 +                }
 41.8271 +                
 41.8272 +                pit.c[0]-=cycdiff;
 41.8273 +                pit.c[1]-=cycdiff;
 41.8274 +                if (ppi.pb&1) pit.c[2]-=cycdiff;
 41.8275 +                if ((pit.c[0]<1)||(pit.c[1]<1)||(pit.c[2]<1)) pit_poll();
 41.8276 +                spktime-=cycdiff;
 41.8277 +                if (spktime<=0.0)
 41.8278 +                {
 41.8279 +                        spktime+=SPKCONST;
 41.8280 +//                        pclog("1Poll spk\n");
 41.8281 +                        pollspk();
 41.8282 +                        pollgussamp();
 41.8283 +                        getsbsamp();
 41.8284 +                        polladlib();
 41.8285 +                        getdacsamp();
 41.8286 +//                        pclog("2Poll spk\n");
 41.8287 +                }
 41.8288 +                soundtime-=cycdiff;
 41.8289 +                if (soundtime<=0.0)
 41.8290 +                {
 41.8291 +                        soundtime+=SOUNDCONST;
 41.8292 +//                        pclog("1Poll sound60hz\n");
 41.8293 +                        pollsound60hz();
 41.8294 +//                        pclog("2Poll sound60hz\n");
 41.8295 +                }
 41.8296 +                gustime-=cycdiff;
 41.8297 +                while (gustime<=0.0)
 41.8298 +                {
 41.8299 +                        gustime+=GUSCONST;
 41.8300 +                        pollgus();
 41.8301 +                }
 41.8302 +                gustime2-=cycdiff;
 41.8303 +                while (gustime2<=0.0)
 41.8304 +                {
 41.8305 +                        gustime2+=GUSCONST2;
 41.8306 +                        pollgus2();
 41.8307 +                }
 41.8308 +                vidtime-=cycdiff;
 41.8309 +                if (vidtime<=0.0)
 41.8310 +                {
 41.8311 +//                        pclog("1Poll video\n");
 41.8312 +                        pollvideo();
 41.8313 +//                        pclog("2Poll video\n");
 41.8314 +                }
 41.8315 +                if (disctime)
 41.8316 +                {
 41.8317 +                        disctime-=(cycdiff);
 41.8318 +                        if (disctime<=0)
 41.8319 +                        {
 41.8320 +//                                pclog("1Poll disc\n");
 41.8321 +                                disctime=0;
 41.8322 +                                fdc_poll();
 41.8323 +//                                pclog("2Poll disc\n");
 41.8324 +                        }
 41.8325 +                }
 41.8326 +                if (mousedelay)
 41.8327 +                {
 41.8328 +                        mousedelay-=20;
 41.8329 +                        if (!mousedelay)
 41.8330 +                        {
 41.8331 +//                                pclog("1Poll mouse\n");
 41.8332 +                                mousecallback();
 41.8333 +//                                pclog("2Poll disc\n");
 41.8334 +                        }
 41.8335 +                }
 41.8336 +                if (sbenable)
 41.8337 +                {
 41.8338 +                        sbcount-=cycdiff;
 41.8339 +                        if (sbcount<0)
 41.8340 +                        {
 41.8341 +                                sbcount+=sblatcho;
 41.8342 +                                pollsb();
 41.8343 +                        }
 41.8344 +                }
 41.8345 +                if (sb_enable_i)
 41.8346 +                {
 41.8347 +                        sb_count_i-=cycdiff;
 41.8348 +                        if (sb_count_i<0)
 41.8349 +                        {
 41.8350 +                                sb_count_i+=sblatchi;
 41.8351 +                                sb_poll_i();
 41.8352 +                        }
 41.8353 +                }
 41.8354 +                if (idecallback[0])
 41.8355 +                {
 41.8356 +                        idecallback[0]--;
 41.8357 +                        if (idecallback[0]<=0)
 41.8358 +                        {
 41.8359 +//                                pclog("IDE time over\n");
 41.8360 +                                idecallback[0]=0;
 41.8361 +                                callbackide(0);
 41.8362 +                        }
 41.8363 +                }
 41.8364 +                if (idecallback[1])
 41.8365 +                {
 41.8366 +                        idecallback[1]--;
 41.8367 +                        if (idecallback[1]<=0)
 41.8368 +                        {
 41.8369 +//                                pclog("IDE time over\n");
 41.8370 +                                idecallback[1]=0;
 41.8371 +                                callbackide(1);
 41.8372 +                        }
 41.8373 +                }
 41.8374 +                rtctime-=cycdiff;
 41.8375 +                if (rtctime<0)
 41.8376 +                {
 41.8377 +                        nvr_rtc();
 41.8378 +                }
 41.8379 +        }
 41.8380 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/src/Makefile.mingw	Sun Apr 21 14:54:35 2013 +0100
    42.3 @@ -0,0 +1,43 @@
    42.4 +VPATH = . mame
    42.5 +CPP  = g++.exe
    42.6 +CC   = gcc.exe
    42.7 +WINDRES = windres.exe
    42.8 +CFLAGS = -O3 -march=i686 -fomit-frame-pointer
    42.9 +OBJ = 286.o 386.o acer386sx.o adlib.o ali1429.o amstrad.o cdrom-ioctl.o cms.o \
   42.10 +	config.o cpu.o dac.o dma.o ega.o fdc.o gus.o harddisk.o \
   42.11 +	headland.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
   42.12 +	keyboard_olim24.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
   42.13 +	mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
   42.14 +     opti.o pc.o pci.o pic.o pit.o \
   42.15 +	ppi.o psg.o sblaster.o serial.o sound.o soundopenal.o um8881f.o \
   42.16 +	vid_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \
   42.17 +	vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_mda.o vid_olivetti_m24.o \
   42.18 +	vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o \
   42.19 +	vid_pc200.o vid_s3.o vid_sdac_ramdac.o vid_stg_ramdac.o \
   42.20 +	vid_svga.o vid_tandy.o vid_tkd8001_ramdac.o vid_tvga.o \
   42.21 +	vid_unk_ramdac.o video.o wd76c10.o win.o win-ddraw.o \
   42.22 +	win-keyboard.o win-mouse.o win-timer.o win-video.o x86.o \
   42.23 +	x86seg.o x87.o xtide.o pc.res
   42.24 +FMOBJ = fmopl.o ymf262.o
   42.25 +
   42.26 +
   42.27 +LIBS = -mwindows -lwinmm -lalut -lopenal32 -lddraw -ldinput -ldxguid
   42.28 +
   42.29 +PCem.exe: $(OBJ) $(FMOBJ)
   42.30 +	$(CC) $(OBJ) $(FMOBJ) -o "PCem.exe" $(LIBS)
   42.31 +
   42.32 +all : PCem.exe
   42.33 +
   42.34 +clean :
   42.35 +	del *.o
   42.36 +	del *.exe
   42.37 +	del *.res
   42.38 +
   42.39 +%.o : %.c
   42.40 +	$(CC) $(CFLAGS) -c $<
   42.41 +
   42.42 +%.o : %.cc
   42.43 +	$(CPP) $(CFLAGS) -c $<
   42.44 +
   42.45 +pc.res: pc.rc
   42.46 +	$(WINDRES) -i pc.rc --input-format=rc -o pc.res -O coff 
   42.47 \ No newline at end of file
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/src/acer386sx.c	Sun Apr 21 14:54:35 2013 +0100
    43.3 @@ -0,0 +1,33 @@
    43.4 +#include "ibm.h"
    43.5 +#include "io.h"
    43.6 +#include "cpu.h"
    43.7 +
    43.8 +#include "acer386sx.h"
    43.9 +
   43.10 +static int acer_index = 0;
   43.11 +static uint8_t acer_regs[256];
   43.12 +
   43.13 +void acer386sx_write(uint16_t addr, uint8_t val)
   43.14 +{
   43.15 +        if (addr & 1)
   43.16 +           acer_regs[acer_index] = val;
   43.17 +        else
   43.18 +           acer_index = val;
   43.19 +}
   43.20 +
   43.21 +uint8_t acer386sx_read(uint16_t addr)
   43.22 +{
   43.23 +        if (addr & 1)
   43.24 +        {
   43.25 +                if ((acer_index >= 0xc0 || acer_index == 0x20) && cpu_iscyrix)
   43.26 +                   return 0xff; /*Don't conflict with Cyrix config registers*/
   43.27 +                return acer_regs[acer_index];
   43.28 +        }
   43.29 +        else
   43.30 +           return acer_index;
   43.31 +}
   43.32 +
   43.33 +void acer386sx_init()
   43.34 +{
   43.35 +        io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL);
   43.36 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/src/acer386sx.h	Sun Apr 21 14:54:35 2013 +0100
    44.3 @@ -0,0 +1,1 @@
    44.4 +void acer386sx_init();
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/src/adlib.c	Sun Apr 21 14:54:35 2013 +0100
    45.3 @@ -0,0 +1,187 @@
    45.4 +#include <stdint.h>
    45.5 +#include <stdlib.h>
    45.6 +#include "ibm.h"
    45.7 +#include "mame/fmopl.h"
    45.8 +#include "mame/ymf262.h"
    45.9 +
   45.10 +/*Interfaces between PCem and the actual Adlib emulator*/
   45.11 +
   45.12 +static int adlib_inited = 0;
   45.13 +int adlibpos=0;
   45.14 +void *YM3812[2];
   45.15 +void *YMF262;
   45.16 +int fm_timers[2][2],fm_timers_enable[2][2];
   45.17 +
   45.18 +void adlib_write(uint16_t a, uint8_t v)
   45.19 +{
   45.20 +//        printf("Adlib write %04X %02X %i\n",a,v,sbtype);
   45.21 +        if (!sbtype) return;
   45.22 +        if (sbtype<SBPRO && a<0x224) return;
   45.23 +        switch (a)
   45.24 +        {
   45.25 +                case 0x220: case 0x221:
   45.26 +                if (sbtype<SBPRO2) ym3812_write(YM3812[0],a,v);
   45.27 +                else               ymf262_write(YMF262,a,v);
   45.28 +                break;
   45.29 +                case 0x222: case 0x223:
   45.30 +                if (sbtype<SBPRO2) ym3812_write(YM3812[1],a,v);
   45.31 +                else               ymf262_write(YMF262,a,v);
   45.32 +                break;
   45.33 +                case 0x228: case 0x229: case 0x388: case 0x389:
   45.34 +                if (sbtype<SBPRO2)
   45.35 +                {
   45.36 +                        ym3812_write(YM3812[0],a,v);
   45.37 +                        ym3812_write(YM3812[1],a,v);
   45.38 +                }
   45.39 +                else
   45.40 +                        ymf262_write(YMF262,a,v);
   45.41 +                break;
   45.42 +        }
   45.43 +}
   45.44 +
   45.45 +uint8_t adlib_read(uint16_t a)
   45.46 +{
   45.47 +        uint8_t temp;
   45.48 +//        printf("Adlib read %04X\n",a);
   45.49 +        if (sbtype>=SBPRO2)
   45.50 +        {
   45.51 +                switch (a)
   45.52 +                {
   45.53 +                        case 0x220: case 0x221:
   45.54 +                        case 0x222: case 0x223:
   45.55 +                        case 0x228: case 0x229:
   45.56 +                        case 0x388: case 0x389:
   45.57 +                        temp=ymf262_read(YMF262,a);
   45.58 +//                        pclog("YMF262 read %03X %02X\n",a,temp);
   45.59 +                        cycles-=(int)(isa_timing * 8);
   45.60 +                        return temp;
   45.61 +                }
   45.62 +        }
   45.63 +        if (!sbtype) return 0xFF;
   45.64 +        switch (a)
   45.65 +        {
   45.66 +                case 0x220: case 0x221:
   45.67 +                if (sbtype<SBPRO) return 0xFF;
   45.68 +                case 0x228: case 0x229:
   45.69 +                case 0x388: case 0x389:
   45.70 +                cycles-=(int)(isa_timing * 8);
   45.71 +                return ym3812_read(YM3812[0],a);
   45.72 +                case 0x222: case 0x223:
   45.73 +                if (sbtype<SBPRO) return 0xFF;
   45.74 +                return ym3812_read(YM3812[1],a);
   45.75 +        }
   45.76 +/*        if (sbtype<SBPRO && a<0x224) return 0xFF;
   45.77 +        if (a==0x222) return adlibstat2;
   45.78 +        if (!(a&1)) return adlibstat;
   45.79 +        return 0;*/
   45.80 +}
   45.81 +
   45.82 +signed short *ad_bufs[4];
   45.83 +int16_t ad_filtbuf[2]={0,0};
   45.84 +void getadlib(signed short *bufl, signed short *bufr, int size)
   45.85 +{
   45.86 +        int c;
   45.87 +        if (sbtype>=SBPRO2)
   45.88 +        {
   45.89 +                ymf262_update_one(YMF262,ad_bufs,size);
   45.90 +                for (c=0;c<size;c++)
   45.91 +                {
   45.92 +                        ad_filtbuf[0]=bufl[c]=(ad_bufs[0][c]/4)+((ad_filtbuf[0]*11)/16);
   45.93 +                        ad_filtbuf[1]=bufr[c]=(ad_bufs[1][c]/4)+((ad_filtbuf[1]*11)/16);
   45.94 +                }
   45.95 +                if (fm_timers_enable[0][0])
   45.96 +                {
   45.97 +                        fm_timers[0][0]--;
   45.98 +                        if (fm_timers[0][0]<0) ymf262_timer_over(YMF262,0);
   45.99 +                }
  45.100 +                if (fm_timers_enable[0][1])
  45.101 +                {
  45.102 +                        fm_timers[0][1]--;
  45.103 +                        if (fm_timers[0][1]<0) ymf262_timer_over(YMF262,1);
  45.104 +                }
  45.105 +        }
  45.106 +        else
  45.107 +        {
  45.108 +                ym3812_update_one(YM3812[0],bufl,size);
  45.109 +                ym3812_update_one(YM3812[1],bufr,size);
  45.110 +                for (c=0;c<size;c++)
  45.111 +                {
  45.112 +                        ad_filtbuf[0]=bufl[c]=(bufl[c]/4)+((ad_filtbuf[0]*11)/16);
  45.113 +                        ad_filtbuf[1]=bufr[c]=(bufr[c]/4)+((ad_filtbuf[1]*11)/16);
  45.114 +                }
  45.115 +                if (fm_timers_enable[0][0])
  45.116 +                {
  45.117 +                        fm_timers[0][0]--;
  45.118 +                        if (fm_timers[0][0]<0) ym3812_timer_over(YM3812[0],0);
  45.119 +                }
  45.120 +                if (fm_timers_enable[0][1])
  45.121 +                {
  45.122 +                        fm_timers[0][1]--;
  45.123 +                        if (fm_timers[0][1]<0) ym3812_timer_over(YM3812[0],1);
  45.124 +                }
  45.125 +                if (fm_timers_enable[1][0])
  45.126 +                {
  45.127 +                        fm_timers[1][0]--;
  45.128 +                        if (fm_timers[1][0]<0) ym3812_timer_over(YM3812[1],0);
  45.129 +                }
  45.130 +                if (fm_timers_enable[1][1])
  45.131 +                {
  45.132 +                        fm_timers[1][1]--;
  45.133 +                        if (fm_timers[1][1]<0) ym3812_timer_over(YM3812[1],1);
  45.134 +                }
  45.135 +        }
  45.136 +//        for (c=0;c<size;c++) buf[c]/=2;
  45.137 +}
  45.138 +
  45.139 +void ym3812_timer_set_0(void *param,int timer,attotime period)
  45.140 +{
  45.141 +        fm_timers[0][timer]=period/20833;
  45.142 +        if (!fm_timers[0][timer]) fm_timers[0][timer]=1;
  45.143 +        fm_timers_enable[0][timer]=(period)?1:0;
  45.144 +}
  45.145 +void ym3812_timer_set_1(void *param,int timer,attotime period)
  45.146 +{
  45.147 +        fm_timers[1][timer]=period/20833;
  45.148 +        if (!fm_timers[1][timer]) fm_timers[1][timer]=1;
  45.149 +        fm_timers_enable[1][timer]=(period)?1:0;
  45.150 +}
  45.151 +
  45.152 +void ymf262_timer_set(void *param,int timer,attotime period)
  45.153 +{
  45.154 +        fm_timers[0][timer]=period/20833;
  45.155 +        if (!fm_timers[0][timer]) fm_timers[0][timer]=1;
  45.156 +        fm_timers_enable[0][timer]=(period)?1:0;
  45.157 +}
  45.158 +
  45.159 +void adlib_init()
  45.160 +{
  45.161 +        if (!adlib_inited)
  45.162 +        {
  45.163 +                ad_bufs[0]=(signed short *)malloc(48000);
  45.164 +                ad_bufs[1]=(signed short *)malloc(48000);
  45.165 +                ad_bufs[2]=(signed short *)malloc(48000);
  45.166 +                ad_bufs[3]=(signed short *)malloc(48000);
  45.167 +                
  45.168 +                YM3812[0]=ym3812_init((void *)NULL,3579545,48000);
  45.169 +                ym3812_reset_chip(YM3812[0]);
  45.170 +                ym3812_set_timer_handler(YM3812[0],ym3812_timer_set_0,NULL);
  45.171 +                YM3812[1]=ym3812_init((void *)NULL,3579545,48000);
  45.172 +                ym3812_reset_chip(YM3812[1]);
  45.173 +                ym3812_set_timer_handler(YM3812[1],ym3812_timer_set_1,NULL);
  45.174 +                
  45.175 +                YMF262=ymf262_init((void *)NULL,3579545*4,48000);
  45.176 +                ymf262_reset_chip(YMF262);
  45.177 +                ymf262_set_timer_handler(YMF262,ymf262_timer_set,NULL);
  45.178 +        }        
  45.179 +        
  45.180 +        adlib_inited = 1;
  45.181 +        
  45.182 +        io_sethandler(0x0388, 0x0002, adlib_read, NULL, NULL, adlib_write, NULL, NULL);
  45.183 +}
  45.184 +
  45.185 +void adlib_reset()
  45.186 +{
  45.187 +        ym3812_reset_chip(YM3812[0]);
  45.188 +        ym3812_reset_chip(YM3812[1]);
  45.189 +        ymf262_reset_chip(YMF262);
  45.190 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/src/ali1429.c	Sun Apr 21 14:54:35 2013 +0100
    46.3 @@ -0,0 +1,76 @@
    46.4 +#include <string.h>
    46.5 +#include "ibm.h"
    46.6 +#include "io.h"
    46.7 +#include "mem.h"
    46.8 +#include "cpu.h"
    46.9 +
   46.10 +#include "ali1429.h"
   46.11 +
   46.12 +static int ali1429_index;
   46.13 +static uint8_t ali1429_regs[256];
   46.14 +
   46.15 +void ali1429_write(uint16_t port, uint8_t val)
   46.16 +{
   46.17 +//        return;
   46.18 +        if (!(port&1)) ali1429_index=val;
   46.19 +        else
   46.20 +        {
   46.21 +                ali1429_regs[ali1429_index]=val;
   46.22 +//                pclog("ALI1429 write %02X %02X %04X:%04X %i\n",ali1429_index,val,CS,pc,ins);
   46.23 +                switch (ali1429_index)
   46.24 +                {
   46.25 +                        case 0x13:
   46.26 +/*                                if (val == 1)
   46.27 +                                { 
   46.28 +                                        times = 1;
   46.29 +                                        ins = 0;
   46.30 +                                        output = 3;
   46.31 +                                }*/
   46.32 +//                                pclog("write 13 %02X %i\n",val,shadowbios);
   46.33 +                                if (!(val&0xC0)) 
   46.34 +                                {
   46.35 +                                       shadowbios=0;
   46.36 +                                        if (!shadowbios_write)
   46.37 +                                           mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   NULL,          NULL,           NULL          );
   46.38 +                                        else
   46.39 +                                           mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml);
   46.40 +                                        flushmmucache();
   46.41 +                                }                                        
   46.42 +                                break;
   46.43 +                        case 0x14:
   46.44 +                        shadowbios=val&1;//((val&3)==1);
   46.45 +                        shadowbios_write=val&2;
   46.46 +                        switch (val & 3)
   46.47 +                        {
   46.48 +                                case 0: mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   NULL,          NULL,           NULL          ); break;
   46.49 +                                case 1: mem_sethandler(0xf0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    NULL,          NULL,           NULL          ); break;
   46.50 +                                case 2: mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml); break;
   46.51 +                                case 3: mem_sethandler(0xf0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml); break;
   46.52 +                        }                                                                                                
   46.53 +                        
   46.54 +//                        if (val==0x43) shadowbios=1;
   46.55 +//                        pclog("Shadow bios %i\n",shadowbios);
   46.56 +                        flushmmucache();
   46.57 +                        break;
   46.58 +                }
   46.59 +        }
   46.60 +}
   46.61 +
   46.62 +uint8_t ali1429_read(uint16_t port)
   46.63 +{
   46.64 +        if (!(port&1)) return ali1429_index;
   46.65 +        if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && cpu_iscyrix)
   46.66 +           return 0xff; /*Don't conflict with Cyrix config registers*/
   46.67 +        return ali1429_regs[ali1429_index];
   46.68 +}
   46.69 +
   46.70 +
   46.71 +void ali1429_reset()
   46.72 +{
   46.73 +        memset(ali1429_regs,0xFF,256);
   46.74 +}
   46.75 +
   46.76 +void ali1429_init()
   46.77 +{
   46.78 +        io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL);
   46.79 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/src/ali1429.h	Sun Apr 21 14:54:35 2013 +0100
    47.3 @@ -0,0 +1,1 @@
    47.4 +void ali1429_init();
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/src/amstrad.c	Sun Apr 21 14:54:35 2013 +0100
    48.3 @@ -0,0 +1,84 @@
    48.4 +#include "ibm.h"
    48.5 +#include "io.h"
    48.6 +#include "keyboard.h"
    48.7 +#include "lpt.h"
    48.8 +#include "mouse.h"
    48.9 +
   48.10 +#include "amstrad.h"
   48.11 +
   48.12 +static uint8_t amstrad_dead;
   48.13 +
   48.14 +uint8_t amstrad_read(uint16_t port)
   48.15 +{
   48.16 +        pclog("amstrad_read : %04X\n",port);
   48.17 +        switch (port)
   48.18 +        {
   48.19 +                case 0x379:
   48.20 +                return 7 | readdacfifo();
   48.21 +                case 0x37a:
   48.22 +                if (romset == ROM_PC1512) return 0x20;
   48.23 +                if (romset == ROM_PC200)  return 0x80;
   48.24 +                return 0;
   48.25 +                case 0xdead:
   48.26 +                return amstrad_dead;
   48.27 +        }
   48.28 +        return 0xff;
   48.29 +}
   48.30 +
   48.31 +void amstrad_write(uint16_t port, uint8_t val)
   48.32 +{
   48.33 +        switch (port)
   48.34 +        {
   48.35 +                case 0xdead:
   48.36 +                amstrad_dead = val;
   48.37 +                break;
   48.38 +        }
   48.39 +}
   48.40 +
   48.41 +static uint8_t mousex,mousey;
   48.42 +
   48.43 +void amstrad_mouse_write(uint16_t addr, uint8_t val)
   48.44 +{
   48.45 +//        pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc);
   48.46 +        if (addr==0x78) mousex=0;
   48.47 +        else            mousey=0;
   48.48 +}
   48.49 +
   48.50 +uint8_t amstrad_mouse_read(uint16_t addr)
   48.51 +{
   48.52 +        uint8_t temp;
   48.53 +//        printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey);
   48.54 +        if (addr==0x78) return mousex;
   48.55 +        return mousey;
   48.56 +}
   48.57 +
   48.58 +static int oldb = 0;
   48.59 +
   48.60 +void amstrad_mouse_poll(int x, int y, int b)
   48.61 +{
   48.62 +        mousex += x;
   48.63 +        mousey += y;
   48.64 +
   48.65 +        if ((b & 1) && !(oldb & 1))
   48.66 +           keyboard_send(0x7e);
   48.67 +        if ((b & 2) && !(oldb & 2))
   48.68 +           keyboard_send(0x7d);
   48.69 +        if (!(b & 1) && (oldb & 1))
   48.70 +           keyboard_send(0xfe);
   48.71 +        if (!(b & 2) && (oldb & 2))
   48.72 +           keyboard_send(0xfd);
   48.73 +        
   48.74 +        oldb = b;
   48.75 +}
   48.76 +
   48.77 +void amstrad_init()
   48.78 +{
   48.79 +        lpt2_remove();
   48.80 +        
   48.81 +        io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL);
   48.82 +        io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL);
   48.83 +        io_sethandler(0x0379, 0x0002, amstrad_read,       NULL, NULL, NULL,                NULL, NULL);
   48.84 +        io_sethandler(0xdead, 0x0001, amstrad_read,       NULL, NULL, amstrad_write,       NULL, NULL);        
   48.85 +
   48.86 +        mouse_poll = amstrad_mouse_poll;
   48.87 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/src/amstrad.h	Sun Apr 21 14:54:35 2013 +0100
    49.3 @@ -0,0 +1,2 @@
    49.4 +void amstrad_init();
    49.5 +
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/src/cdrom-ioctl.c	Sun Apr 21 14:54:35 2013 +0100
    50.3 @@ -0,0 +1,475 @@
    50.4 +/*Win32 CD-ROM support via IOCTL*/
    50.5 +
    50.6 +#include <windows.h>
    50.7 +#include <io.h>
    50.8 +#include "ddk/ntddcdrm.h"
    50.9 +//#include "ntddcdrm.h"
   50.10 +#include "ibm.h"
   50.11 +#include "ide.h"
   50.12 +#include "cdrom-ioctl.h"
   50.13 +
   50.14 +int cdrom_drive;
   50.15 +
   50.16 +typedef struct _CDROM_TOC_SESSION_DATA {
   50.17 +  UCHAR      Length[2];
   50.18 +  UCHAR      FirstCompleteSession;
   50.19 +  UCHAR      LastCompleteSession;
   50.20 +  TRACK_DATA TrackData[1];
   50.21 +} CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA;
   50.22 +static ATAPI ioctl_atapi;
   50.23 +
   50.24 +static int ioctl_inited = 0;
   50.25 +static char ioctl_path[8];
   50.26 +static void ioctl_close(void);
   50.27 +static HANDLE hIOCTL;
   50.28 +static CDROM_TOC toc;
   50.29 +static int tocvalid = 0;
   50.30 +
   50.31 +#define MSFtoLBA(m,s,f)  (((((m*60)+s)*75)+f)-150)
   50.32 +
   50.33 +enum
   50.34 +{
   50.35 +    CD_STOPPED = 0,
   50.36 +    CD_PLAYING,
   50.37 +    CD_PAUSED
   50.38 +};
   50.39 +
   50.40 +static int ioctl_cd_state = CD_STOPPED;
   50.41 +static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0;
   50.42 +
   50.43 +#define BUF_SIZE 32768
   50.44 +static int16_t cd_buffer[BUF_SIZE];
   50.45 +static int cd_buflen = 0;
   50.46 +void ioctl_audio_callback(int16_t *output, int len)
   50.47 +{
   50.48 +	RAW_READ_INFO in;
   50.49 +	DWORD count;
   50.50 +	int c;
   50.51 +//	return;
   50.52 +//        pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
   50.53 +        if (ioctl_cd_state != CD_PLAYING) 
   50.54 +        {
   50.55 +                memset(output, 0, len * 2);
   50.56 +                return;
   50.57 +        }
   50.58 +        while (cd_buflen < len)
   50.59 +        {
   50.60 +                if (ioctl_cd_pos < ioctl_cd_end)
   50.61 +                {
   50.62 +		        in.DiskOffset.LowPart  = ioctl_cd_pos * 2048;
   50.63 +        		in.DiskOffset.HighPart = 0;
   50.64 +        		in.SectorCount	       = 1;
   50.65 +        		in.TrackMode	       = CDDA;		
   50.66 +        		ioctl_open(0);
   50.67 +//        		pclog("Read to %i\n", cd_buflen);
   50.68 +        		if (!DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &cd_buffer[cd_buflen], 2352, &count, NULL))
   50.69 +        		{
   50.70 +//                                pclog("DeviceIoControl returned false\n");
   50.71 +                                memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
   50.72 +                                ioctl_cd_state = CD_STOPPED;
   50.73 +                                cd_buflen = len;
   50.74 +                        }
   50.75 +                        else
   50.76 +                        {
   50.77 +//                                pclog("DeviceIoControl returned true\n");
   50.78 +                                ioctl_cd_pos++;
   50.79 +                                cd_buflen += (2352 / 2);
   50.80 +                        }
   50.81 +                        ioctl_close();
   50.82 +                }
   50.83 +                else
   50.84 +                {
   50.85 +                        memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
   50.86 +                        ioctl_cd_state = CD_STOPPED;
   50.87 +                        cd_buflen = len;                        
   50.88 +                }
   50.89 +        }
   50.90 +        memcpy(output, cd_buffer, len * 2);
   50.91 +//        for (c = 0; c < BUF_SIZE - len; c++)
   50.92 +//            cd_buffer[c] = cd_buffer[c + cd_buflen];
   50.93 +        memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2);
   50.94 +        cd_buflen -= len;
   50.95 +//        pclog("Done %i\n", GetTickCount());
   50.96 +}
   50.97 +
   50.98 +void ioctl_audio_stop()
   50.99 +{
  50.100 +        ioctl_cd_state = CD_STOPPED;
  50.101 +}
  50.102 +
  50.103 +static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
  50.104 +{
  50.105 +        if (!cdrom_drive) return;
  50.106 +        pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
  50.107 +        if (ismsf)
  50.108 +        {
  50.109 +                pos = (pos & 0xff) + (((pos >> 8) & 0xff) * 75) + (((pos >> 16) & 0xff) * 75 * 60);
  50.110 +                len = (len & 0xff) + (((len >> 8) & 0xff) * 75) + (((len >> 16) & 0xff) * 75 * 60);
  50.111 +                pclog("MSF - pos = %08X len = %08X\n", pos, len);
  50.112 +        }
  50.113 +        else
  50.114 +           len += pos;
  50.115 +        ioctl_cd_pos   = pos;// + 150;
  50.116 +        ioctl_cd_end   = len;// + 150;
  50.117 +        ioctl_cd_state = CD_PLAYING;
  50.118 +        pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len);        
  50.119 +/*        CDROM_PLAY_AUDIO_MSF msf;
  50.120 +        long size;
  50.121 +        BOOL b;
  50.122 +        if (ismsf)
  50.123 +        {
  50.124 +                msf.StartingF=pos&0xFF;
  50.125 +                msf.StartingS=(pos>>8)&0xFF;
  50.126 +                msf.StartingM=(pos>>16)&0xFF;
  50.127 +                msf.EndingF=len&0xFF;
  50.128 +                msf.EndingS=(len>>8)&0xFF;
  50.129 +                msf.EndingM=(len>>16)&0xFF;
  50.130 +        }
  50.131 +        else
  50.132 +        {
  50.133 +                msf.StartingF=(uint8_t)(addr%75); addr/=75;
  50.134 +                msf.StartingS=(uint8_t)(addr%60); addr/=60;
  50.135 +                msf.StartingM=(uint8_t)(addr);
  50.136 +                addr=pos+len+150;
  50.137 +                msf.EndingF=(uint8_t)(addr%75); addr/=75;
  50.138 +                msf.EndingS=(uint8_t)(addr%60); addr/=60;
  50.139 +                msf.EndingM=(uint8_t)(addr);
  50.140 +        }
  50.141 +        ioctl_open(0);
  50.142 +        b = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL);
  50.143 +        pclog("DeviceIoControl returns %i\n", (int) b);
  50.144 +        ioctl_close();*/
  50.145 +}
  50.146 +
  50.147 +static void ioctl_pause(void)
  50.148 +{
  50.149 +        long size;
  50.150 +        if (!cdrom_drive) return;
  50.151 +        if (ioctl_cd_state == CD_PLAYING)
  50.152 +           ioctl_cd_state = CD_PAUSED;
  50.153 +//        ioctl_open(0);
  50.154 +//        DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO,NULL,0,NULL,0,&size,NULL);
  50.155 +//        ioctl_close();
  50.156 +}
  50.157 +
  50.158 +static void ioctl_resume(void)
  50.159 +{
  50.160 +        long size;
  50.161 +        if (!cdrom_drive) return;
  50.162 +        if (ioctl_cd_state == CD_PAUSED)
  50.163 +           ioctl_cd_state = CD_PLAYING;
  50.164 +//        ioctl_open(0);
  50.165 +//        DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO,NULL,0,NULL,0,&size,NULL);
  50.166 +//        ioctl_close();
  50.167 +}
  50.168 +
  50.169 +static void ioctl_stop(void)
  50.170 +{
  50.171 +        long size;
  50.172 +        if (!cdrom_drive) return;
  50.173 +        ioctl_cd_state = CD_STOPPED;
  50.174 +//        ioctl_open(0);
  50.175 +//        DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO,NULL,0,NULL,0,&size,NULL);
  50.176 +//        ioctl_close();
  50.177 +}
  50.178 +
  50.179 +static void ioctl_seek(uint32_t pos)
  50.180 +{
  50.181 +        long size;
  50.182 +        if (!cdrom_drive) return;
  50.183 + //       ioctl_cd_state = CD_STOPPED;
  50.184 +        pclog("Seek %08X\n", pos);
  50.185 +        ioctl_cd_pos   = pos;
  50.186 +        ioctl_cd_state = CD_STOPPED;
  50.187 +/*        pos+=150;
  50.188 +        CDROM_SEEK_AUDIO_MSF msf;
  50.189 +        msf.F=(uint8_t)(pos%75); pos/=75;
  50.190 +        msf.S=(uint8_t)(pos%60); pos/=60;
  50.191 +        msf.M=(uint8_t)(pos);
  50.192 +//        pclog("Seek to %02i:%02i:%02i\n",msf.M,msf.S,msf.F);
  50.193 +        ioctl_open(0);
  50.194 +        DeviceIoControl(hIOCTL,IOCTL_CDROM_SEEK_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL);
  50.195 +        ioctl_close();*/
  50.196 +}
  50.197 +
  50.198 +static int ioctl_ready(void)
  50.199 +{
  50.200 +        long size;
  50.201 +        int temp;
  50.202 +        CDROM_TOC ltoc;
  50.203 +//        pclog("Ready? %i\n",cdrom_drive);
  50.204 +        if (!cdrom_drive) return 0;
  50.205 +        ioctl_open(0);
  50.206 +        temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&ltoc,sizeof(ltoc),&size,NULL);
  50.207 +        ioctl_close();
  50.208 +        if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) ||
  50.209 +            (ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) ||
  50.210 +            (ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]) ||
  50.211 +            !tocvalid)
  50.212 +        {
  50.213 +                ioctl_cd_state = CD_STOPPED;                
  50.214 +  /*              pclog("Not ready %02X %02X %02X  %02X %02X %02X  %i\n",ltoc.TrackData[ltoc.LastTrack].Address[1],ltoc.TrackData[ltoc.LastTrack].Address[2],ltoc.TrackData[ltoc.LastTrack].Address[3],
  50.215 +                                                                        toc.TrackData[ltoc.LastTrack].Address[1], toc.TrackData[ltoc.LastTrack].Address[2], toc.TrackData[ltoc.LastTrack].Address[3],tocvalid);*/
  50.216 +        //        atapi_discchanged();
  50.217 +/*                ioctl_open(0);
  50.218 +                temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL);
  50.219 +                ioctl_close();*/
  50.220 +                toc=ltoc;
  50.221 +                tocvalid=1;
  50.222 +                return 0;
  50.223 +        }
  50.224 +//        pclog("IOCTL says ready\n");
  50.225 +        return 1;
  50.226 +//        return (temp)?1:0;
  50.227 +}
  50.228 +
  50.229 +static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
  50.230 +{
  50.231 +	CDROM_SUB_Q_DATA_FORMAT insub;
  50.232 +	SUB_Q_CHANNEL_DATA sub;
  50.233 +	long size;
  50.234 +	int pos=0;
  50.235 +	int c;
  50.236 +	uint32_t temp, cdpos;
  50.237 +        if (!cdrom_drive) return 0;
  50.238 +	insub.Format = IOCTL_CDROM_CURRENT_POSITION;
  50.239 +        ioctl_open(0);
  50.240 +        DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL);
  50.241 +        ioctl_close();
  50.242 +        b[pos++]=sub.CurrentPosition.Control;
  50.243 +        b[pos++]=sub.CurrentPosition.TrackNumber;
  50.244 +        b[pos++]=sub.CurrentPosition.IndexNumber;
  50.245 +/*        pclog("Read subchannel %02X %02X %02X %02X%02X%02X%02X %02X%02X%02X%02X\n",sub.CurrentPosition.Control,sub.CurrentPosition.TrackNumber,sub.CurrentPosition.IndexNumber,
  50.246 +                sub.CurrentPosition.AbsoluteAddress[0],sub.CurrentPosition.AbsoluteAddress[1],sub.CurrentPosition.AbsoluteAddress[2],sub.CurrentPosition.AbsoluteAddress[3],
  50.247 +                sub.CurrentPosition.TrackRelativeAddress[0],sub.CurrentPosition.TrackRelativeAddress[1],sub.CurrentPosition.TrackRelativeAddress[2],sub.CurrentPosition.TrackRelativeAddress[3]);*/
  50.248 +        cdpos = ioctl_cd_pos;                
  50.249 +        if (msf)
  50.250 +        {
  50.251 +                b[pos++] = (uint8_t)(cdpos % 75); cdpos /= 75;
  50.252 +                b[pos++] = (uint8_t)(cdpos % 60); cdpos /= 60;
  50.253 +                b[pos++] = (uint8_t)cdpos;
  50.254 +                b[pos++] = 0;
  50.255 +                b[pos++] = (uint8_t)(cdpos % 75); cdpos /= 75;
  50.256 +                b[pos++] = (uint8_t)(cdpos % 60); cdpos /= 60;
  50.257 +                b[pos++] = (uint8_t)cdpos;
  50.258 +                b[pos++] = 0;
  50.259 +
  50.260 +
  50.261 +//                for (c=0;c<4;c++) b[pos++]=sub.CurrentPosition.AbsoluteAddress[c];
  50.262 +//                for (c=0;c<4;c++) b[pos++]=sub.CurrentPosition.TrackRelativeAddress[c];
  50.263 +        }
  50.264 +        else
  50.265 +        {
  50.266 +                b[pos++] = cdpos & 0xff;
  50.267 +                b[pos++] = (cdpos >> 8) & 0xff;
  50.268 +                b[pos++] = (cdpos >> 16) & 0xff;
  50.269 +                b[pos++] = (cdpos >> 24) & 0xff;
  50.270 +                b[pos++] = cdpos & 0xff;
  50.271 +                b[pos++] = (cdpos >> 8) & 0xff;
  50.272 +                b[pos++] = (cdpos >> 16) & 0xff;
  50.273 +                b[pos++] = (cdpos >> 24) & 0xff;
  50.274 +/*                temp=MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1],sub.CurrentPosition.AbsoluteAddress[2],sub.CurrentPosition.AbsoluteAddress[3]);
  50.275 +                b[pos++]=temp>>24;
  50.276 +                b[pos++]=temp>>16;
  50.277 +                b[pos++]=temp>>8;
  50.278 +                b[pos++]=temp;
  50.279 +                temp=MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1],sub.CurrentPosition.TrackRelativeAddress[2],sub.CurrentPosition.TrackRelativeAddress[3]);
  50.280 +                b[pos++]=temp>>24;
  50.281 +                b[pos++]=temp>>16;
  50.282 +                b[pos++]=temp>>8;
  50.283 +                b[pos++]=temp;*/
  50.284 +        }
  50.285 +        if (ioctl_cd_state == CD_PLAYING) return 0x11;
  50.286 +        if (ioctl_cd_state == CD_PAUSED)  return 0x12;
  50.287 +        return 0x13;
  50.288 +//        return sub.CurrentPosition.Header.AudioStatus;
  50.289 +}
  50.290 +
  50.291 +static void ioctl_eject(void)
  50.292 +{
  50.293 +        long size;
  50.294 +        if (!cdrom_drive) return;
  50.295 +        ioctl_cd_state = CD_STOPPED;        
  50.296 +        ioctl_open(0);
  50.297 +        DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL);
  50.298 +        ioctl_close();
  50.299 +}
  50.300 +
  50.301 +static void ioctl_load(void)
  50.302 +{
  50.303 +        long size;
  50.304 +        if (!cdrom_drive) return;
  50.305 +        ioctl_cd_state = CD_STOPPED;        
  50.306 +        ioctl_open(0);
  50.307 +        DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL);
  50.308 +        ioctl_close();
  50.309 +}
  50.310 +
  50.311 +static void ioctl_readsector(uint8_t *b, int sector)
  50.312 +{
  50.313 +        LARGE_INTEGER pos;
  50.314 +        long size;
  50.315 +        if (!cdrom_drive) return;
  50.316 +        ioctl_cd_state = CD_STOPPED;        
  50.317 +        pos.QuadPart=sector*2048;
  50.318 +        ioctl_open(0);
  50.319 +        SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
  50.320 +        ReadFile(hIOCTL,b,2048,&size,NULL);
  50.321 +        ioctl_close();
  50.322 +}
  50.323 +
  50.324 +static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
  50.325 +{
  50.326 +        int len=4;
  50.327 +        long size;
  50.328 +        int c,d;
  50.329 +        uint32_t temp;
  50.330 +        if (!cdrom_drive) return 0;
  50.331 +        ioctl_cd_state = CD_STOPPED;        
  50.332 +        ioctl_open(0);
  50.333 +        DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL);
  50.334 +        ioctl_close();
  50.335 +        tocvalid=1;
  50.336 +//        pclog("Read TOC done! %i\n",single);
  50.337 +        b[2]=toc.FirstTrack;
  50.338 +        b[3]=toc.LastTrack;
  50.339 +        d=0;
  50.340 +        for (c=0;c<=toc.LastTrack;c++)
  50.341 +        {
  50.342 +                if (toc.TrackData[c].TrackNumber>=starttrack)
  50.343 +                {
  50.344 +                        d=c;
  50.345 +                        break;
  50.346 +                }
  50.347 +        }
  50.348 +        b[2]=toc.TrackData[c].TrackNumber;
  50.349 +        for (c=d;c<=toc.LastTrack;c++)
  50.350 +        {
  50.351 +                if ((len+8)>maxlen) break;
  50.352 +//                pclog("Len %i max %i Track %02X - %02X %02X %i %i %i %i %08X\n",len,maxlen,toc.TrackData[c].TrackNumber,toc.TrackData[c].Adr,toc.TrackData[c].Control,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3],MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]));
  50.353 +                b[len++]=0; /*Reserved*/
  50.354 +                b[len++]=(toc.TrackData[c].Adr<<4)|toc.TrackData[c].Control;
  50.355 +                b[len++]=toc.TrackData[c].TrackNumber;
  50.356 +                b[len++]=0; /*Reserved*/
  50.357 +                if (msf)
  50.358 +                {
  50.359 +                        b[len++]=toc.TrackData[c].Address[0];
  50.360 +                        b[len++]=toc.TrackData[c].Address[1];
  50.361 +                        b[len++]=toc.TrackData[c].Address[2];
  50.362 +                        b[len++]=toc.TrackData[c].Address[3];
  50.363 +                }
  50.364 +                else
  50.365 +                {
  50.366 +                        temp=MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
  50.367 +                        b[len++]=temp>>24;
  50.368 +                        b[len++]=temp>>16;
  50.369 +                        b[len++]=temp>>8;
  50.370 +                        b[len++]=temp;
  50.371 +                }
  50.372 +                if (single) break;
  50.373 +        }
  50.374 +        b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
  50.375 +        b[1] = (uint8_t)((len-2) & 0xff);
  50.376 +/*        pclog("Table of Contents (%i bytes) : \n",size);
  50.377 +        pclog("First track - %02X\n",toc.FirstTrack);
  50.378 +        pclog("Last  track - %02X\n",toc.LastTrack);
  50.379 +        for (c=0;c<=toc.LastTrack;c++)
  50.380 +            pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
  50.381 +        for (c=0;c<=toc.LastTrack;c++)
  50.382 +            pclog("Track %02X - number %02X control %02X adr %02X address %06X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]));*/
  50.383 +        return len;
  50.384 +}
  50.385 +
  50.386 +static void ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
  50.387 +{
  50.388 +        int len=4;
  50.389 +        int size;
  50.390 +        uint32_t temp;
  50.391 +        CDROM_READ_TOC_EX toc_ex;
  50.392 +        CDROM_TOC_SESSION_DATA toc;
  50.393 +        if (!cdrom_drive) return;
  50.394 +        ioctl_cd_state = CD_STOPPED;        
  50.395 +        memset(&toc_ex,0,sizeof(toc_ex));
  50.396 +        memset(&toc,0,sizeof(toc));
  50.397 +        toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION;
  50.398 +        toc_ex.Msf=msf;
  50.399 +        toc_ex.SessionTrack=0;
  50.400 +        ioctl_open(0);
  50.401 +        DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL);
  50.402 +        ioctl_close();
  50.403 +//        pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber);
  50.404 +        b[2]=toc.FirstCompleteSession;
  50.405 +        b[3]=toc.LastCompleteSession;
  50.406 +                b[len++]=0; /*Reserved*/
  50.407 +                b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control;
  50.408 +                b[len++]=toc.TrackData[0].TrackNumber;
  50.409 +                b[len++]=0; /*Reserved*/
  50.410 +                if (msf)
  50.411 +                {
  50.412 +                        b[len++]=toc.TrackData[0].Address[0];
  50.413 +                        b[len++]=toc.TrackData[0].Address[1];
  50.414 +                        b[len++]=toc.TrackData[0].Address[2];
  50.415 +                        b[len++]=toc.TrackData[0].Address[3];
  50.416 +                }
  50.417 +                else
  50.418 +                {
  50.419 +                        temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]);
  50.420 +                        b[len++]=temp>>24;
  50.421 +                        b[len++]=temp>>16;
  50.422 +                        b[len++]=temp>>8;
  50.423 +                        b[len++]=temp;
  50.424 +                }
  50.425 +}
  50.426 +
  50.427 +int ioctl_open(char d)
  50.428 +{
  50.429 +//        char s[8];
  50.430 +        if (!ioctl_inited)
  50.431 +        {
  50.432 +                sprintf(ioctl_path,"\\\\.\\%c:",d);
  50.433 +                pclog("Path is %s\n",ioctl_path);
  50.434 +                tocvalid=0;
  50.435 +        }
  50.436 +//        pclog("Opening %s\n",ioctl_path);
  50.437 +	hIOCTL	= CreateFile(/*"\\\\.\\g:"*/ioctl_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
  50.438 +	if (!hIOCTL)
  50.439 +	{
  50.440 +                //fatal("IOCTL");
  50.441 +        }
  50.442 +        atapi=&ioctl_atapi;
  50.443 +        if (!ioctl_inited)
  50.444 +        {
  50.445 +                ioctl_inited=1;
  50.446 +                CloseHandle(hIOCTL);
  50.447 +        }
  50.448 +        return 0;
  50.449 +}
  50.450 +
  50.451 +static void ioctl_close(void)
  50.452 +{
  50.453 +        CloseHandle(hIOCTL);
  50.454 +}
  50.455 +
  50.456 +static void ioctl_exit(void)
  50.457 +{
  50.458 +        ioctl_stop();
  50.459 +        ioctl_inited=0;
  50.460 +        tocvalid=0;
  50.461 +}
  50.462 +
  50.463 +static ATAPI ioctl_atapi=
  50.464 +{
  50.465 +        ioctl_ready,
  50.466 +        ioctl_readtoc,
  50.467 +        ioctl_readtoc_session,
  50.468 +        ioctl_getcurrentsubchannel,
  50.469 +        ioctl_readsector,
  50.470 +        ioctl_playaudio,
  50.471 +        ioctl_seek,
  50.472 +        ioctl_load,
  50.473 +        ioctl_eject,
  50.474 +        ioctl_pause,
  50.475 +        ioctl_resume,
  50.476 +        ioctl_stop,
  50.477 +        ioctl_exit
  50.478 +};
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/src/cdrom-ioctl.h	Sun Apr 21 14:54:35 2013 +0100
    51.3 @@ -0,0 +1,9 @@
    51.4 +#ifndef CDROM_IOCTL_H
    51.5 +#define CDROM_IOCTL_H
    51.6 +
    51.7 +/* this header file lists the functions provided by
    51.8 +   various platform specific cdrom-ioctl files */
    51.9 +
   51.10 +extern int ioctl_open(char d);
   51.11 +   
   51.12 +#endif /* ! CDROM_IOCTL_H */
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/src/cms.c	Sun Apr 21 14:54:35 2013 +0100
    52.3 @@ -0,0 +1,141 @@
    52.4 +#include <stdio.h>
    52.5 +#include "ibm.h"
    52.6 +
    52.7 +int cmsaddrs[2];
    52.8 +uint8_t cmsregs[2][32];
    52.9 +uint16_t cmslatch[12],cmsnoisefreq[12];
   52.10 +int cmsfreq[12];
   52.11 +float cmscount[12];
   52.12 +int cmsvol[12][2];
   52.13 +int cmsstat[12];
   52.14 +uint16_t cmsnoise[4];
   52.15 +int cmsnoisecount[4];
   52.16 +int cmsnoisetype[4];
   52.17 +
   52.18 +#define CMSCONST (62500.0/44100.0)
   52.19 +
   52.20 +void getcms(signed short *p, int size)
   52.21 +{
   52.22 +        int c,d;
   52.23 +        int ena[12],noiseena[12];
   52.24 +        for (c=0;c<6;c++)
   52.25 +        {
   52.26 +                ena[c]=(cmsregs[0][0x14]&(1<<c));
   52.27 +                ena[c+6]=(cmsregs[1][0x14]&(1<<c));
   52.28 +        }
   52.29 +        if (!(cmsregs[0][0x1C]&1))
   52.30 +        {
   52.31 +                for (c=0;c<6;c++) ena[c]=0;
   52.32 +        }
   52.33 +        if (!(cmsregs[1][0x1C]&1))
   52.34 +        {
   52.35 +                for (c=0;c<6;c++) ena[c+6]=0;
   52.36 +        }
   52.37 +        for (c=0;c<6;c++)
   52.38 +        {
   52.39 +                noiseena[c]=(cmsregs[0][0x15]&(1<<c));
   52.40 +                noiseena[c+6]=(cmsregs[1][0x15]&(1<<c));
   52.41 +        }
   52.42 +        if (!(cmsregs[0][0x1C]&1))
   52.43 +        {
   52.44 +                for (c=0;c<6;c++) noiseena[c]=0;
   52.45 +        }
   52.46 +        if (!(cmsregs[1][0x1C]&1))
   52.47 +        {
   52.48 +                for (c=0;c<6;c++) noiseena[c+6]=0;
   52.49 +        }
   52.50 +        for (c=0;c<4;c++)
   52.51 +        {
   52.52 +                switch (cmsnoisetype[c])
   52.53 +                {
   52.54 +                        case 0: cmsnoisefreq[c]=31250; break;
   52.55 +                        case 1: cmsnoisefreq[c]=15625; break;
   52.56 +                        case 2: cmsnoisefreq[c]=7812; break;
   52.57 +                        case 3: cmsnoisefreq[c]=cmsfreq[c*3]; break;
   52.58 +                }
   52.59 +        }
   52.60 +        for (c=0;c<(size<<1);c+=2)
   52.61 +        {
   52.62 +                p[c]=0;
   52.63 +                p[c+1]=0;
   52.64 +                for (d=0;d<12;d++)
   52.65 +                {
   52.66 +                        if (ena[d])
   52.67 +                        {
   52.68 +                                if (cmsstat[d]) p[c]  +=(cmsvol[d][0]*90);
   52.69 +                                if (cmsstat[d]) p[c+1]+=(cmsvol[d][1]*90);
   52.70 +                                cmscount[d]+=cmsfreq[d];
   52.71 +                                if (cmscount[d]>=(22050))
   52.72 +                                {
   52.73 +                                        cmscount[d]-=(22050);
   52.74 +                                        cmsstat[d]^=1;
   52.75 +                                }
   52.76 +                        }
   52.77 +                        else if (noiseena[d])
   52.78 +                        {
   52.79 +                                if (cmsnoise[d/3]&1) p[c]  +=(cmsvol[d][0]*90);
   52.80 +                                if (cmsnoise[d/3]&1) p[c+1]+=(cmsvol[d][0]*90);
   52.81 +                        }
   52.82 +                }
   52.83 +                for (d=0;d<4;d++)
   52.84 +                {
   52.85 +                        cmsnoisecount[d]+=cmsnoisefreq[d];
   52.86 +                        while (cmsnoisecount[d]>=22050)
   52.87 +                        {
   52.88 +                                cmsnoisecount[d]-=22050;
   52.89 +                                cmsnoise[d]<<=1;
   52.90 +                                if (!(((cmsnoise[d]&0x4000)>>8)^(cmsnoise[d]&0x40))) cmsnoise[d]|=1;
   52.91 +                        }
   52.92 +                }
   52.93 +        }
   52.94 +}
   52.95 +
   52.96 +void writecms(uint16_t addr, uint8_t val)
   52.97 +{
   52.98 +        int voice;
   52.99 +        int chip=(addr&2)>>1;
  52.100 +        if (addr&1)
  52.101 +           cmsaddrs[chip]=val&31;
  52.102 +        else
  52.103 +        {
  52.104 +                cmsregs[chip][cmsaddrs[chip]&31]=val;
  52.105 +                switch (cmsaddrs[chip]&31)
  52.106 +                {
  52.107 +                        case 0x00: case 0x01: case 0x02: /*Volume*/
  52.108 +                        case 0x03: case 0x04: case 0x05:
  52.109 +                        voice=cmsaddrs[chip]&7;
  52.110 +                        if (chip) voice+=6;
  52.111 +                        cmsvol[voice][0]=val&0xF;//((val&0xF)+(val>>4))>>1;
  52.112 +                        cmsvol[voice][1]=val>>4;
  52.113 +                        break;
  52.114 +                        case 0x08: case 0x09: case 0x0A: /*Frequency*/
  52.115 +                        case 0x0B: case 0x0C: case 0x0D:
  52.116 +                        voice=cmsaddrs[chip]&7;
  52.117 +                        if (chip) voice+=6;
  52.118 +                        cmslatch[voice]=(cmslatch[voice]&0x700)|val;
  52.119 +                        cmsfreq[voice]=(15625<<(cmslatch[voice]>>8))/(511-(cmslatch[voice]&255));
  52.120 +                        break;
  52.121 +                        case 0x10: case 0x11: case 0x12: /*Octave*/
  52.122 +                        voice=(cmsaddrs[chip]&3)<<1;
  52.123 +                        if (chip) voice+=6;
  52.124 +                        cmslatch[voice]=(cmslatch[voice]&0xFF)|((val&7)<<8);
  52.125 +                        cmslatch[voice+1]=(cmslatch[voice+1]&0xFF)|((val&0x70)<<4);
  52.126 +                        cmsfreq[voice]=(15625<<(cmslatch[voice]>>8))/(511-(cmslatch[voice]&255));
  52.127 +                        cmsfreq[voice+1]=(15625<<(cmslatch[voice+1]>>8))/(511-(cmslatch[voice+1]&255));
  52.128 +                        break;
  52.129 +                        case 0x16: /*Noise*/
  52.130 +                        voice=chip*2;
  52.131 +                        cmsnoisetype[voice]=val&3;
  52.132 +                        cmsnoisetype[voice+1]=(val>>4)&3;
  52.133 +                        break;
  52.134 +                }
  52.135 +        }
  52.136 +}
  52.137 +
  52.138 +uint8_t readcms(uint16_t addr)
  52.139 +{
  52.140 +        int chip=(addr&2)>>1;
  52.141 +        if (addr&1) return cmsaddrs[chip];
  52.142 +        return cmsregs[chip][cmsaddrs[chip]&31];
  52.143 +}
  52.144 +
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/src/config.c	Sun Apr 21 14:54:35 2013 +0100
    53.3 @@ -0,0 +1,166 @@
    53.4 +#include <stdio.h>
    53.5 +#include <string.h>
    53.6 +#include "config.h"
    53.7 +
    53.8 +static char config_file[256];
    53.9 +
   53.10 +void set_config_file(char *s)
   53.11 +{
   53.12 +        strcpy(config_file, s);
   53.13 +}
   53.14 +
   53.15 +void config_new()
   53.16 +{
   53.17 +        FILE *f = fopen(config_file, "wt");
   53.18 +        fclose(f);
   53.19 +}
   53.20 +
   53.21 +int get_config_int(char *head, char *name, int def)
   53.22 +{
   53.23 +        char buffer[256];
   53.24 +        char name2[256];
   53.25 +        FILE *f = fopen(config_file, "rt");
   53.26 +        int c, d;
   53.27 +        int res = def;
   53.28 +        
   53.29 +        if (!f)
   53.30 +           return def;
   53.31 +           
   53.32 +        pclog("Searching for %s\n", name);
   53.33 +        
   53.34 +        while (1)
   53.35 +        {
   53.36 +                fgets(buffer, 255, f);
   53.37 +                if (feof(f)) break;
   53.38 +                
   53.39 +                c = d = 0;
   53.40 +                
   53.41 +                while (buffer[c] == ' ' && buffer[c])
   53.42 +                      c++;
   53.43 +                      
   53.44 +                if (!buffer[c]) continue;
   53.45 +                
   53.46 +                while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
   53.47 +                        name2[d++] = buffer[c++];
   53.48 +                
   53.49 +                if (!buffer[c]) continue;
   53.50 +                name2[d] = 0;
   53.51 +                
   53.52 +                pclog("Comparing %s and %s\n", name, name2);
   53.53 +                if (strcmp(name, name2)) continue;
   53.54 +                pclog("Found!\n");
   53.55 +
   53.56 +                while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])                
   53.57 +                        c++;
   53.58 +                        
   53.59 +                if (!buffer[c]) continue;
   53.60 +                
   53.61 +                sscanf(&buffer[c], "%i", &res);
   53.62 +                pclog("Reading value - %i\n", res);
   53.63 +                break;
   53.64 +        }
   53.65 +        
   53.66 +        fclose(f);
   53.67 +        return res;
   53.68 +}
   53.69 +
   53.70 +char config_return_string[256];
   53.71 +
   53.72 +char *get_config_string(char *head, char *name, char *def)
   53.73 +{
   53.74 +        char buffer[256];
   53.75 +        char name2[256];
   53.76 +        FILE *f = fopen(config_file, "rt");
   53.77 +        int c, d;
   53.78 +        
   53.79 +        strcpy(config_return_string, def);
   53.80 +        
   53.81 +        if (!f)
   53.82 +           return config_return_string;
   53.83 +           
   53.84 +        pclog("Searching for %s\n", name);
   53.85 +        
   53.86 +        while (1)
   53.87 +        {
   53.88 +                fgets(buffer, 255, f);
   53.89 +                if (feof(f)) break;
   53.90 +                
   53.91 +                c = d = 0;
   53.92 +                
   53.93 +                while (buffer[c] == ' ' && buffer[c])
   53.94 +                      c++;
   53.95 +                      
   53.96 +                if (!buffer[c]) continue;
   53.97 +                
   53.98 +                while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
   53.99 +                        name2[d++] = buffer[c++];
  53.100 +                
  53.101 +                if (!buffer[c]) continue;
  53.102 +                name2[d] = 0;
  53.103 +                
  53.104 +                pclog("Comparing %s and %s\n", name, name2);
  53.105 +                if (strcmp(name, name2)) continue;
  53.106 +                pclog("Found!\n");
  53.107 +
  53.108 +                while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])                
  53.109 +                        c++;
  53.110 +                        
  53.111 +                if (!buffer[c]) continue;
  53.112 +                
  53.113 +                strcpy(config_return_string, &buffer[c]);
  53.114 +                
  53.115 +                c = strlen(config_return_string) - 1;
  53.116 +                pclog("string len %i\n", c);
  53.117 +                while (config_return_string[c] <= 32 && config_return_string[c]) 
  53.118 +                      config_return_string[c--] = 0;
  53.119 +
  53.120 +                pclog("Reading value - %s\n", config_return_string);
  53.121 +                break;
  53.122 +        }
  53.123 +        
  53.124 +        fclose(f);
  53.125 +        return config_return_string;
  53.126 +}
  53.127 +
  53.128 +void set_config_int(char *head, char *name, int val)
  53.129 +{
  53.130 +        FILE *f = fopen(config_file, "at");
  53.131 +        if (!f) pclog("set_config_int - !f\n");
  53.132 +        fprintf(f, "%s = %i\n", name, val);
  53.133 +        pclog("Write %s = %i\n", name, val);
  53.134 +        fclose(f);
  53.135 +        pclog("fclose\n");
  53.136 +}
  53.137 +
  53.138 +void set_config_string(char *head, char *name, char *val)
  53.139 +{
  53.140 +        FILE *f = fopen(config_file, "at");
  53.141 +        if (!f) pclog("set_config_string - !f\n");
  53.142 +        fprintf(f, "%s = %s\n", name, val);
  53.143 +        pclog("Write %s = %s\n", name, val);
  53.144 +        fclose(f);
  53.145 +}
  53.146 +
  53.147 +char *get_filename(char *s)
  53.148 +{
  53.149 +        int c = strlen(s) - 1;
  53.150 +        while (c > 0)
  53.151 +        {
  53.152 +                if (s[c] == '/' || s[c] == '\\')
  53.153 +                   return &s[c+1];
  53.154 +                c--;
  53.155 +        }
  53.156 +        return s;
  53.157 +}
  53.158 +
  53.159 +void append_filename(char *dest, char *s1, char *s2, int size)
  53.160 +{
  53.161 +        sprintf(dest, "%s%s", s1, s2);
  53.162 +}
  53.163 +
  53.164 +void put_backslash(char *s)
  53.165 +{
  53.166 +        int c = strlen(s) - 1;
  53.167 +        if (s[c] != '/' && s[c] != '\\')
  53.168 +           s[c] = '/';
  53.169 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/src/config.h	Sun Apr 21 14:54:35 2013 +0100
    54.3 @@ -0,0 +1,5 @@
    54.4 +void set_config_file(char *s);
    54.5 +int get_config_int(char *head, char *name, int def);
    54.6 +char *get_config_string(char *head, char *name, char *def);
    54.7 +void set_config_int(char *head, char *name, int val);
    54.8 +void set_config_string(char *head, char *name, char *val);
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/src/cpu.c	Sun Apr 21 14:54:35 2013 +0100
    55.3 @@ -0,0 +1,411 @@
    55.4 +#include "ibm.h"
    55.5 +#include "cpu.h"
    55.6 +#include "model.h"
    55.7 +#include "io.h"
    55.8 +
    55.9 +int cpu = 3, cpu_manufacturer = 0;
   55.10 +CPU *cpu_s;
   55.11 +int cpu_multi;
   55.12 +int cpu_iscyrix;
   55.13 +int cpu_16bitbus;
   55.14 +int cpu_busspeed;
   55.15 +
   55.16 +int timing_rr;
   55.17 +int timing_mr, timing_mrl;
   55.18 +int timing_rm, timing_rml;
   55.19 +int timing_mm, timing_mml;
   55.20 +int timing_bt, timing_bnt;
   55.21 +
   55.22 +/*Available cpuspeeds :
   55.23 +        0 = 16 MHz
   55.24 +        1 = 20 MHz
   55.25 +        2 = 25 MHz
   55.26 +        3 = 33 MHz
   55.27 +        4 = 40 MHz
   55.28 +        5 = 50 MHz
   55.29 +        6 = 66 MHz
   55.30 +        7 = 75 MHz
   55.31 +        8 = 80 MHz
   55.32 +        9 = 90 MHz
   55.33 +        10 = 100 MHz
   55.34 +        11 = 120 MHz
   55.35 +        12 = 133 MHz
   55.36 +        13 = 150 MHz
   55.37 +        14 = 160 MHz
   55.38 +*/
   55.39 +
   55.40 +CPU cpus_8088[] =
   55.41 +{
   55.42 +        /*8088 standard*/
   55.43 +        {"8088/4.77",    CPU_8088,  0,  4772727, 1, 0, 0, 0},
   55.44 +        {"8088/8",       CPU_8088,  1,  8000000, 1, 0, 0, 0},
   55.45 +        {"8088/10",      CPU_8088,  2, 10000000, 1, 0, 0, 0},
   55.46 +        {"8088/12",      CPU_8088,  3, 12000000, 1, 0, 0, 0},
   55.47 +        {"8088/16",      CPU_8088,  4, 16000000, 1, 0, 0, 0},
   55.48 +        {"",             -1,        0, 0, 0, 0}
   55.49 +};
   55.50 +
   55.51 +CPU cpus_8086[] =
   55.52 +{
   55.53 +        /*8086 standard*/
   55.54 +        {"8086/7.16",    CPU_8086,  1,  3579545*2,     1, 0, 0, 0},
   55.55 +        {"8086/8",       CPU_8086,  1,  8000000,       1, 0, 0, 0},
   55.56 +        {"8086/9.54",    CPU_8086,  1, (3579545*8)/3,  1, 0, 0, 0},
   55.57 +        {"8086/10",      CPU_8086,  2, 10000000,       1, 0, 0, 0},
   55.58 +        {"8086/12",      CPU_8086,  3, 12000000,       1, 0, 0, 0},
   55.59 +        {"8086/16",      CPU_8086,  4, 16000000,       1, 0, 0, 0},
   55.60 +        {"",             -1,        0, 0, 0, 0}
   55.61 +};
   55.62 +
   55.63 +CPU cpus_pc1512[] =
   55.64 +{
   55.65 +        /*8086 Amstrad*/
   55.66 +        {"8086/8",       CPU_8086,  1,  8000000,       1, 0, 0, 0},
   55.67 +        {"",             -1,        0, 0, 0, 0}
   55.68 +};
   55.69 +
   55.70 +CPU cpus_286[] =
   55.71 +{
   55.72 +        /*286*/
   55.73 +        {"286/6",        CPU_286,   0,  6000000, 1, 0, 0, 0},
   55.74 +        {"286/8",        CPU_286,   1,  8000000, 1, 0, 0, 0},
   55.75 +        {"286/10",       CPU_286,   2, 10000000, 1, 0, 0, 0},
   55.76 +        {"286/12",       CPU_286,   3, 12000000, 1, 0, 0, 0},
   55.77 +        {"286/16",       CPU_286,   4, 16000000, 1, 0, 0, 0},
   55.78 +        {"286/20",       CPU_286,   5, 20000000, 1, 0, 0, 0},
   55.79 +        {"286/25",       CPU_286,   6, 25000000, 1, 0, 0, 0},
   55.80 +        {"",             -1,        0, 0, 0, 0}
   55.81 +};
   55.82 +
   55.83 +CPU cpus_ibmat[] =
   55.84 +{
   55.85 +        /*286*/
   55.86 +        {"286/6",        CPU_286,   0,  6000000, 1, 0, 0, 0},
   55.87 +        {"",             -1,        0, 0, 0, 0}
   55.88 +};
   55.89 +
   55.90 +CPU cpus_i386[] =
   55.91 +{
   55.92 +        /*i386*/
   55.93 +        {"i386SX/16",    CPU_386SX, 0, 16000000, 1, 0x2308, 0, 0},
   55.94 +        {"i386SX/20",    CPU_386SX, 1, 20000000, 1, 0x2308, 0, 0},
   55.95 +        {"i386SX/25",    CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
   55.96 +        {"i386SX/33",    CPU_386SX, 3, 33333333, 1, 0x2308, 0, 0},
   55.97 +        {"i386DX/16",    CPU_386DX, 0, 16000000, 1, 0x0308, 0, 0},
   55.98 +        {"i386DX/20",    CPU_386DX, 1, 20000000, 1, 0x0308, 0, 0},
   55.99 +        {"i386DX/25",    CPU_386DX, 2, 25000000, 1, 0x0308, 0, 0},
  55.100 +        {"i386DX/33",    CPU_386DX, 3, 33333333, 1, 0x0308, 0, 0},
  55.101 +        {"",             -1,        0, 0, 0}
  55.102 +};
  55.103 +
  55.104 +CPU cpus_acer[] =
  55.105 +{
  55.106 +        /*i386*/
  55.107 +        {"i386SX/25",    CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
  55.108 +        {"",             -1,        0, 0, 0}
  55.109 +};
  55.110 +
  55.111 +CPU cpus_Am386[] =
  55.112 +{
  55.113 +        /*Am386*/
  55.114 +        {"Am386SX/16",   CPU_386SX, 0, 16000000, 1, 0x2308, 0, 0},
  55.115 +        {"Am386SX/20",   CPU_386SX, 1, 20000000, 1, 0x2308, 0, 0},
  55.116 +        {"Am386SX/25",   CPU_386SX, 2, 25000000, 1, 0x2308, 0, 0},
  55.117 +        {"Am386SX/33",   CPU_386SX, 3, 33333333, 1, 0x2308, 0, 0},
  55.118 +        {"Am386SX/40",   CPU_386SX, 4, 40000000, 1, 0x2308, 0, 0},
  55.119 +        {"Am386DX/25",   CPU_386DX, 2, 25000000, 1, 0x0308, 0, 0},
  55.120 +        {"Am386DX/33",   CPU_386DX, 3, 33333333, 1, 0x0308, 0, 0},
  55.121 +        {"Am386DX/40",   CPU_386DX, 4, 40000000, 1, 0x0308, 0, 0},
  55.122 +        {"",             -1,        0, 0, 0}
  55.123 +};
  55.124 +
  55.125 +CPU cpus_486SDLC[] =
  55.126 +{
  55.127 +        /*Cx486SLC/DLC*/
  55.128 +        {"Cx486SLC/20",  CPU_486SLC, 1, 20000000, 1, 0, 0, 0x0000},
  55.129 +        {"Cx486SLC/25",  CPU_486SLC, 2, 25000000, 1, 0, 0, 0x0000},
  55.130 +        {"Cx486SLC/33",  CPU_486SLC, 3, 33333333, 1, 0, 0, 0x0000},
  55.131 +        {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0, 0x0006},
  55.132 +        {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0, 0x0006},
  55.133 +        {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0, 0x0006},
  55.134 +        {"Cx486DLC/25",  CPU_486DLC, 2, 25000000, 1, 0, 0, 0x0001},
  55.135 +        {"Cx486DLC/33",  CPU_486DLC, 3, 33333333, 1, 0, 0, 0x0001},
  55.136 +        {"Cx486DLC/40",  CPU_486DLC, 4, 40000000, 1, 0, 0, 0x0001},
  55.137 +        {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0, 0x0007},
  55.138 +        {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0, 0x0007},
  55.139 +        {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0, 0x0007},
  55.140 +        {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0, 0x0007},
  55.141 +        {"",             -1,        0, 0, 0}
  55.142 +};
  55.143 +
  55.144 +CPU cpus_i486[] =
  55.145 +{
  55.146 +        /*i486*/
  55.147 +        {"i486SX/16",    CPU_i486SX, 0,  16000000, 1, 0x42a, 0, 0},
  55.148 +        {"i486SX/20",    CPU_i486SX, 1,  20000000, 1, 0x42a, 0, 0},
  55.149 +        {"i486SX/25",    CPU_i486SX, 2,  25000000, 1, 0x42a, 0, 0},
  55.150 +        {"i486SX/33",    CPU_i486SX, 3,  33333333, 1, 0x42a, 0, 0},
  55.151 +        {"i486SX2/50",   CPU_i486SX, 5,  50000000, 2, 0x45b, 0, 0},
  55.152 +        {"i486DX/25",    CPU_i486DX, 2,  25000000, 1, 0x404, 0, 0},
  55.153 +        {"i486DX/33",    CPU_i486DX, 3,  33333333, 1, 0x404, 0, 0},
  55.154 +        {"i486DX/50",    CPU_i486DX, 5,  50000000, 1, 0x404, 0, 0},
  55.155 +        {"i486DX2/40",   CPU_i486DX, 4,  40000000, 2, 0x430, 0, 0},
  55.156 +        {"i486DX2/50",   CPU_i486DX, 5,  50000000, 2, 0x430, 0, 0},
  55.157 +        {"i486DX2/66",   CPU_i486DX, 6,  66666666, 2, 0x430, 0, 0},
  55.158 +        {"iDX4/75",      CPU_i486DX, 7,  75000000, 3, 0x481, 0x481, 0}, /*CPUID available on DX4, >= 75 MHz*/
  55.159 +        {"iDX4/100",     CPU_i486DX,10, 100000000, 3, 0x481, 0x481, 0}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
  55.160 +        {"",             -1,        0, 0, 0}
  55.161 +};
  55.162 +
  55.163 +CPU cpus_Am486[] =
  55.164 +{
  55.165 +        /*Am486/5x86*/
  55.166 +        {"Am486SX/33",   CPU_Am486SX,  3,  33333333, 1, 0x42a, 0, 0},
  55.167 +        {"Am486SX/40",   CPU_Am486SX,  4,  40000000, 1, 0x42a, 0, 0},
  55.168 +        {"Am486SX2/50",  CPU_Am486SX,  5,  50000000, 2, 0x45b, 0x45b, 0}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
  55.169 +        {"Am486SX2/66",  CPU_Am486SX,  6,  66666666, 2, 0x45b, 0x45b, 0}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
  55.170 +        {"Am486DX/33",   CPU_Am486DX,  3,  33333333, 1, 0x430, 0, 0},
  55.171 +        {"Am486DX/40",   CPU_Am486DX,  4,  40000000, 1, 0x430, 0, 0},
  55.172 +        {"Am486DX2/50",  CPU_Am486DX,  5,  50000000, 2, 0x470, 0x470, 0},
  55.173 +        {"Am486DX2/66",  CPU_Am486DX,  6,  66666666, 2, 0x470, 0x470, 0},
  55.174 +        {"Am486DX2/80",  CPU_Am486DX,  8,  80000000, 2, 0x470, 0x470, 0},
  55.175 +        {"Am486DX4/75",  CPU_Am486DX,  7,  75000000, 3, 0x482, 0x482, 0},
  55.176 +        {"Am486DX4/90",  CPU_Am486DX,  9,  90000000, 3, 0x482, 0x482, 0},
  55.177 +        {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 0x482, 0x482, 0},
  55.178 +        {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 0x482, 0x482, 0},
  55.179 +        {"Am5x86/P75",   CPU_Am486DX, 12, 133333333, 4, 0x4e0, 0x4e0, 0},
  55.180 +        {"Am5x86/P75+",  CPU_Am486DX, 13, 150000000, 4, 0x4e0, 0x4e0, 0},
  55.181 +        {"",             -1,        0, 0, 0}
  55.182 +};
  55.183 +
  55.184 +CPU cpus_Cx486[] =
  55.185 +{
  55.186 +        /*Cx486/5x86*/
  55.187 +        {"Cx486S/25",    CPU_Cx486S,   2,  25000000, 1, 0x420, 0, 0x0010},
  55.188 +        {"Cx486S/33",    CPU_Cx486S,   3,  33333333, 1, 0x420, 0, 0x0010},
  55.189 +        {"Cx486S/40",    CPU_Cx486S,   4,  40000000, 1, 0x420, 0, 0x0010},
  55.190 +        {"Cx486DX/33",   CPU_Cx486DX,  3,  33333333, 1, 0x430, 0, 0x051a},
  55.191 +        {"Cx486DX/40",   CPU_Cx486DX,  4,  40000000, 1, 0x430, 0, 0x051a},
  55.192 +        {"Cx486DX2/50",  CPU_Cx486DX,  5,  50000000, 2, 0x430, 0, 0x081b},
  55.193 +        {"Cx486DX2/66",  CPU_Cx486DX,  6,  66666666, 2, 0x430, 0, 0x0b1b},
  55.194 +        {"Cx486DX2/80",  CPU_Cx486DX,  8,  80000000, 2, 0x430, 0, 0x311b},
  55.195 +        {"Cx486DX4/75",  CPU_Cx486DX,  7,  75000000, 3, 0x480, 0, 0x361f},
  55.196 +        {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 0x480, 0, 0x361f},
  55.197 +        {"Cx5x86/100",   CPU_Cx5x86,  10, 100000000, 3, 0x480, 0, 0x002f},
  55.198 +        {"Cx5x86/120",   CPU_Cx5x86,  11, 120000000, 3, 0x480, 0, 0x002f},
  55.199 +        {"Cx5x86/133",   CPU_Cx5x86,  12, 133333333, 4, 0x480, 0, 0x002f},
  55.200 +        {"",             -1,        0, 0, 0}
  55.201 +};
  55.202 +
  55.203 +void cpu_set_edx()
  55.204 +{
  55.205 +        EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
  55.206 +}
  55.207 +
  55.208 +void cpu_set()
  55.209 +{
  55.210 +        CPU *cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
  55.211 +
  55.212 +        CPUID    = cpu_s->cpuid_model;
  55.213 +        cpuspeed = cpu_s->speed;
  55.214 +        is8086   = (cpu_s->cpu_type >= CPU_8088);
  55.215 +        is486    = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
  55.216 +        hasfpu   = (cpu_s->cpu_type >= CPU_i486DX);
  55.217 +        cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86);
  55.218 +        cpu_16bitbus = (cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
  55.219 +        if (cpu_s->multi) 
  55.220 +           cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
  55.221 +        cpu_multi = cpu_s->multi;
  55.222 +        
  55.223 +        if (cpu_iscyrix)
  55.224 +           io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL);
  55.225 +        else
  55.226 +           io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL);
  55.227 +        
  55.228 +        pclog("hasfpu - %i\n",hasfpu);
  55.229 +        pclog("is486 - %i  %i\n",is486,cpu_s->cpu_type);
  55.230 +        
  55.231 +        switch (cpu_s->cpu_type)
  55.232 +        {
  55.233 +                case CPU_386SX:
  55.234 +                timing_rr  = 2;   /*register dest - register src*/
  55.235 +                timing_rm  = 6;   /*register dest - memory src*/
  55.236 +                timing_mr  = 7;   /*memory dest   - register src*/
  55.237 +                timing_mm  = 6;   /*memory dest   - memory src*/
  55.238 +                timing_rml = 8;   /*register dest - memory src long*/
  55.239 +                timing_mrl = 11;  /*memory dest   - register src long*/
  55.240 +                timing_mml = 10;  /*memory dest   - memory src*/
  55.241 +                timing_bt  = 7-3; /*branch taken*/
  55.242 +                timing_bnt = 3;   /*branch not taken*/
  55.243 +                break;
  55.244 +
  55.245 +                case CPU_386DX:
  55.246 +                timing_rr  = 2; /*register dest - register src*/
  55.247 +                timing_rm  = 6; /*register dest - memory src*/
  55.248 +                timing_mr  = 7; /*memory dest   - register src*/
  55.249 +                timing_mm  = 6; /*memory dest   - memory src*/
  55.250 +                timing_rml = 6; /*register dest - memory src long*/
  55.251 +                timing_mrl = 7; /*memory dest   - register src long*/
  55.252 +                timing_mml = 6; /*memory dest   - memory src*/
  55.253 +                timing_bt  = 7-3; /*branch taken*/
  55.254 +                timing_bnt = 3; /*branch not taken*/
  55.255 +                break;
  55.256 +                
  55.257 +                case CPU_486SLC:
  55.258 +                timing_rr  = 1; /*register dest - register src*/
  55.259 +                timing_rm  = 3; /*register dest - memory src*/
  55.260 +                timing_mr  = 5; /*memory dest   - register src*/
  55.261 +                timing_mm  = 3;
  55.262 +                timing_rml = 5; /*register dest - memory src long*/
  55.263 +                timing_mrl = 7; /*memory dest   - register src long*/
  55.264 +                timing_mml = 7;
  55.265 +                timing_bt  = 6-1; /*branch taken*/
  55.266 +                timing_bnt = 1; /*branch not taken*/
  55.267 +                break;
  55.268 +                
  55.269 +                case CPU_486DLC:
  55.270 +                timing_rr  = 1; /*register dest - register src*/
  55.271 +                timing_rm  = 3; /*register dest - memory src*/
  55.272 +                timing_mr  = 3; /*memory dest   - register src*/
  55.273 +                timing_mm  = 3;
  55.274 +                timing_rml = 3; /*register dest - memory src long*/
  55.275 +                timing_mrl = 3; /*memory dest   - register src long*/
  55.276 +                timing_mml = 3;
  55.277 +                timing_bt  = 6-1; /*branch taken*/
  55.278 +                timing_bnt = 1; /*branch not taken*/
  55.279 +                break;
  55.280 +                
  55.281 +                case CPU_i486SX:
  55.282 +                case CPU_i486DX:
  55.283 +                timing_rr  = 1; /*register dest - register src*/
  55.284 +                timing_rm  = 2; /*register dest - memory src*/
  55.285 +                timing_mr  = 3; /*memory dest   - register src*/
  55.286 +                timing_mm  = 3;
  55.287 +                timing_rml = 2; /*register dest - memory src long*/
  55.288 +                timing_mrl = 3; /*memory dest   - register src long*/
  55.289 +                timing_mml = 3;
  55.290 +                timing_bt  = 3-1; /*branch taken*/
  55.291 +                timing_bnt = 1; /*branch not taken*/
  55.292 +                break;
  55.293 +
  55.294 +                case CPU_Am486SX:
  55.295 +                case CPU_Am486DX:
  55.296 +                /*AMD timing identical to Intel*/
  55.297 +                timing_rr  = 1; /*register dest - register src*/
  55.298 +                timing_rm  = 2; /*register dest - memory src*/
  55.299 +                timing_mr  = 3; /*memory dest   - register src*/
  55.300 +                timing_mm  = 3;
  55.301 +                timing_rml = 2; /*register dest - memory src long*/
  55.302 +                timing_mrl = 3; /*memory dest   - register src long*/
  55.303 +                timing_mml = 3;
  55.304 +                timing_bt  = 3-1; /*branch taken*/
  55.305 +                timing_bnt = 1; /*branch not taken*/
  55.306 +                break;
  55.307 +                
  55.308 +                case CPU_Cx486S:
  55.309 +                case CPU_Cx486DX:
  55.310 +                timing_rr  = 1; /*register dest - register src*/
  55.311 +                timing_rm  = 3; /*register dest - memory src*/
  55.312 +                timing_mr  = 3; /*memory dest   - register src*/
  55.313 +                timing_mm  = 3;
  55.314 +                timing_rml = 3; /*register dest - memory src long*/
  55.315 +                timing_mrl = 3; /*memory dest   - register src long*/
  55.316 +                timing_mml = 3;
  55.317 +                timing_bt  = 4-1; /*branch taken*/
  55.318 +                timing_bnt = 1; /*branch not taken*/
  55.319 +                break;
  55.320 +                
  55.321 +                case CPU_Cx5x86:
  55.322 +                timing_rr  = 1; /*register dest - register src*/
  55.323 +                timing_rm  = 1; /*register dest - memory src*/
  55.324 +                timing_mr  = 2; /*memory dest   - register src*/
  55.325 +                timing_mm  = 2;
  55.326 +                timing_rml = 1; /*register dest - memory src long*/
  55.327 +                timing_mrl = 2; /*memory dest   - register src long*/
  55.328 +                timing_mml = 2;
  55.329 +                timing_bt  = 5-1; /*branch taken*/
  55.330 +                timing_bnt = 1; /*branch not taken*/
  55.331 +                break;
  55.332 +        }
  55.333 +}
  55.334 +
  55.335 +void cpu_CPUID()
  55.336 +{
  55.337 +        switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
  55.338 +        {
  55.339 +                case CPU_i486DX:
  55.340 +                if (!EAX)
  55.341 +                {
  55.342 +                        EAX = 0x00000001;
  55.343 +                        EBX = 0x756e6547;
  55.344 +                        EDX = 0x49656e69;
  55.345 +                        ECX = 0x6c65746e;
  55.346 +                }
  55.347 +                else if (EAX == 1)
  55.348 +                {
  55.349 +                        EAX = CPUID;
  55.350 +                        EBX = ECX = 0;
  55.351 +                        EDX = 1; /*FPU*/
  55.352 +                }
  55.353 +                else
  55.354 +                   EAX = 0;
  55.355 +                break;
  55.356 +
  55.357 +                case CPU_Am486SX:
  55.358 +                if (!EAX)
  55.359 +                {
  55.360 +                        EBX = 0x68747541;
  55.361 +                        ECX = 0x444D4163;
  55.362 +                        EDX = 0x69746E65;
  55.363 +                }
  55.364 +                else if (EAX == 1)
  55.365 +                {
  55.366 +                        EAX = CPUID;
  55.367 +                        EBX = ECX = EDX = 0; /*No FPU*/
  55.368 +                }
  55.369 +                else
  55.370 +                   EAX = 0;
  55.371 +                break;
  55.372 +
  55.373 +                case CPU_Am486DX:
  55.374 +                if (!EAX)
  55.375 +                {
  55.376 +                        EBX = 0x68747541;
  55.377 +                        ECX = 0x444D4163;
  55.378 +                        EDX = 0x69746E65;
  55.379 +                }
  55.380 +                else if (EAX == 1)
  55.381 +                {
  55.382 +                        EAX = CPUID;
  55.383 +                        EBX = ECX = 0;
  55.384 +                        EDX = 1; /*FPU*/
  55.385 +                }
  55.386 +                else
  55.387 +                   EAX = 0;
  55.388 +                break;
  55.389 +        }
  55.390 +}
  55.391 +
  55.392 +
  55.393 +static int cyrix_addr;
  55.394 +
  55.395 +void cyrix_write(uint16_t addr, uint8_t val)
  55.396 +{
  55.397 +        if (!(addr & 1)) cyrix_addr = val;
  55.398 +//        else pclog("Write Cyrix %02X %02X\n",cyrix_addr,val);
  55.399 +}
  55.400 +
  55.401 +uint8_t cyrix_read(uint16_t addr)
  55.402 +{
  55.403 +        if (addr & 1)
  55.404 +        {
  55.405 +                switch (cyrix_addr)
  55.406 +                {
  55.407 +                        case 0xfe: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id & 0xff;
  55.408 +                        case 0xff: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id >> 8;
  55.409 +                }
  55.410 +                if ((cyrix_addr & ~0xf0) == 0xc0) return 0xff;
  55.411 +                if (cyrix_addr == 0x20 && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_Cx5x86) return 0xff;
  55.412 +        }
  55.413 +        return 0xff;
  55.414 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/src/cpu.h	Sun Apr 21 14:54:35 2013 +0100
    56.3 @@ -0,0 +1,71 @@
    56.4 +extern int cpu, cpu_manufacturer;
    56.5 +
    56.6 +/*808x class CPUs*/
    56.7 +#define CPU_8088 0
    56.8 +#define CPU_8086 1
    56.9 +
   56.10 +/*286 class CPUs*/
   56.11 +#define CPU_286 2
   56.12 +
   56.13 +/*386 class CPUs*/
   56.14 +#define CPU_386SX  3
   56.15 +#define CPU_386DX  4
   56.16 +#define CPU_486SLC 5
   56.17 +#define CPU_486DLC 6
   56.18 +
   56.19 +/*486 class CPUs*/
   56.20 +#define CPU_i486SX  7
   56.21 +#define CPU_Am486SX 8
   56.22 +#define CPU_Cx486S  9
   56.23 +#define CPU_i486DX  10
   56.24 +#define CPU_Am486DX 11
   56.25 +#define CPU_Cx486DX 12
   56.26 +#define CPU_Cx5x86  13
   56.27 +
   56.28 +#define MANU_INTEL 0
   56.29 +#define MANU_AMD   1
   56.30 +#define MANU_CYRIX 2
   56.31 +
   56.32 +extern int timing_rr;
   56.33 +extern int timing_mr, timing_mrl;
   56.34 +extern int timing_rm, timing_rml;
   56.35 +extern int timing_mm, timing_mml;
   56.36 +extern int timing_bt, timing_bnt;
   56.37 +
   56.38 +
   56.39 +
   56.40 +typedef struct
   56.41 +{
   56.42 +        char name[16];
   56.43 +        int cpu_type;
   56.44 +        int speed;
   56.45 +        int rspeed;
   56.46 +        int multi;
   56.47 +        uint32_t edx_reset;
   56.48 +        uint32_t cpuid_model;
   56.49 +        uint16_t cyrix_id;
   56.50 +} CPU;
   56.51 +
   56.52 +extern CPU cpus_8088[];
   56.53 +extern CPU cpus_8086[];
   56.54 +extern CPU cpus_286[];
   56.55 +extern CPU cpus_i386[];
   56.56 +extern CPU cpus_Am386[];
   56.57 +extern CPU cpus_486SDLC[];
   56.58 +extern CPU cpus_i486[];
   56.59 +extern CPU cpus_Am486[];
   56.60 +extern CPU cpus_Cx486[];
   56.61 +
   56.62 +extern CPU cpus_pc1512[];
   56.63 +extern CPU cpus_ibmat[];
   56.64 +extern CPU cpus_acer[];
   56.65 +
   56.66 +extern int cpu_iscyrix;
   56.67 +extern int cpu_16bitbus;
   56.68 +extern int cpu_busspeed;
   56.69 +extern int cpu_multi;
   56.70 +
   56.71 +void cyrix_write(uint16_t addr, uint8_t val);
   56.72 +uint8_t cyrix_read(uint16_t addr);
   56.73 +
   56.74 +extern int is8086;
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/src/dac.c	Sun Apr 21 14:54:35 2013 +0100
    57.3 @@ -0,0 +1,68 @@
    57.4 +#include "ibm.h"
    57.5 +
    57.6 +uint8_t dac,dac2;
    57.7 +uint8_t dacctrl;
    57.8 +int lptfifo;
    57.9 +uint8_t dssbuffer[16];
   57.10 +int dssstart=0,dssend=0;
   57.11 +int dssmode=0;
   57.12 +
   57.13 +void writedac(uint16_t addr, uint8_t val)
   57.14 +{
   57.15 +        if (dssmode) dac2=val;
   57.16 +        else         dac=val;
   57.17 +}
   57.18 +
   57.19 +void writedacctrl(uint16_t addr, uint8_t val)
   57.20 +{
   57.21 +//        printf("Write DAC ctrl %02X %i\n",val,lptfifo);
   57.22 +        if (dacctrl&8 && !(val&8) && (lptfifo!=16))
   57.23 +        {
   57.24 +//                dac=dac2;
   57.25 +                dssbuffer[dssend++]=dac2;
   57.26 +                dssend&=15;
   57.27 +                lptfifo++;
   57.28 +        }
   57.29 +        dacctrl=val;
   57.30 +}
   57.31 +
   57.32 +uint8_t readdacfifo()
   57.33 +{
   57.34 +        if (lptfifo==16) return 0x40;
   57.35 +        return 0;
   57.36 +}
   57.37 +
   57.38 +void pollss()
   57.39 +{
   57.40 +        if (lptfifo)
   57.41 +        {
   57.42 +                dac=dssbuffer[dssstart++];
   57.43 +                dssstart&=15;
   57.44 +                lptfifo--;
   57.45 +        }
   57.46 +}
   57.47 +
   57.48 +int16_t dacbuffer[SOUNDBUFLEN+20];
   57.49 +int dacbufferpos=0;
   57.50 +void getdacsamp()
   57.51 +{
   57.52 +        if (dacbufferpos<SOUNDBUFLEN+20) dacbuffer[dacbufferpos++]=(((int)(unsigned int)dac)-0x80)*0x20;
   57.53 +}
   57.54 +
   57.55 +void adddac(int16_t *p)
   57.56 +{
   57.57 +        int c;
   57.58 +        if (dacbufferpos>SOUNDBUFLEN) dacbufferpos=SOUNDBUFLEN;
   57.59 +        for (c=0;c<dacbufferpos;c++)
   57.60 +        {
   57.61 +                p[c<<1]+=(dacbuffer[c]);
   57.62 +                p[(c<<1)+1]+=(dacbuffer[c]);
   57.63 +        }
   57.64 +        for (;c<SOUNDBUFLEN;c++)
   57.65 +        {
   57.66 +                p[c<<1]+=(dacbuffer[dacbufferpos-1]);
   57.67 +                p[(c<<1)+1]+=(dacbuffer[dacbufferpos-1]);
   57.68 +        }
   57.69 +        dacbufferpos=0;
   57.70 +}
   57.71 +
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/src/dma.c	Sun Apr 21 14:54:35 2013 +0100
    58.3 @@ -0,0 +1,490 @@
    58.4 +#include "ibm.h"
    58.5 +#include "video.h"
    58.6 +#include "io.h"
    58.7 +#include "dma.h"
    58.8 +
    58.9 +extern int ins;
   58.10 +int output;
   58.11 +uint8_t dmaregs[16];
   58.12 +int dmaon[4];
   58.13 +uint8_t dma16regs[16];
   58.14 +int dma16on[4];
   58.15 +
   58.16 +void dma_reset()
   58.17 +{
   58.18 +        int c;
   58.19 +        dma.wp=0;
   58.20 +        for (c=0;c<16;c++) dmaregs[c]=0;
   58.21 +        for (c=0;c<4;c++)
   58.22 +        {
   58.23 +                dma.mode[c]=0;
   58.24 +                dma.ac[c]=0;
   58.25 +                dma.cc[c]=0;
   58.26 +                dma.ab[c]=0;
   58.27 +                dma.cb[c]=0;
   58.28 +        }
   58.29 +        dma.m=0;
   58.30 +        
   58.31 +        dma16.wp=0;
   58.32 +        for (c=0;c<16;c++) dma16regs[c]=0;
   58.33 +        for (c=0;c<4;c++)
   58.34 +        {
   58.35 +                dma16.mode[c]=0;
   58.36 +                dma16.ac[c]=0;
   58.37 +                dma16.cc[c]=0;
   58.38 +                dma16.ab[c]=0;
   58.39 +                dma16.cb[c]=0;
   58.40 +        }
   58.41 +        dma16.m=0;
   58.42 +}
   58.43 +
   58.44 +uint8_t dma_read(uint16_t addr)
   58.45 +{
   58.46 +        uint8_t temp;
   58.47 +//        printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
   58.48 +        switch (addr&0xF)
   58.49 +        {
   58.50 +                case 0:
   58.51 +/*                if (((dma.mode[0]>>2)&3)==2)
   58.52 +                {
   58.53 +                        dma.ac[0]++;
   58.54 +                        dma.cc[0]--;
   58.55 +                        if (dma.cc[0]<0)
   58.56 +                        {
   58.57 +                                dma.ac[0]=dma.ab[0];
   58.58 +                                dma.cc[0]=dma.cb[0];
   58.59 +                        }
   58.60 +                }*/
   58.61 +                case 2: case 4: case 6: /*Address registers*/
   58.62 +                dma.wp^=1;
   58.63 +                if (dma.wp) return dma.ac[(addr>>1)&3]&0xFF;
   58.64 +                return dma.ac[(addr>>1)&3]>>8;
   58.65 +                case 1: case 3: case 5: case 7: /*Count registers*/
   58.66 +//                printf("DMA count %i = %04X\n", (addr>>1)&3, dma.cc[(addr>>1)&3]);
   58.67 +                dma.wp^=1;
   58.68 +                if (dma.wp) temp=dma.cc[(addr>>1)&3]&0xFF;
   58.69 +                else        temp=dma.cc[(addr>>1)&3]>>8;
   58.70 +//                printf("%02X\n",temp);
   58.71 +                return temp;
   58.72 +                case 8: /*Status register*/
   58.73 +                temp=dma.stat;
   58.74 +                dma.stat=0;
   58.75 +                return temp|1;
   58.76 +                case 0xD:
   58.77 +                return 0;
   58.78 +        }
   58.79 +//        printf("Bad DMA read %04X %04X:%04X\n",addr,CS,pc);
   58.80 +        return dmaregs[addr&0xF];
   58.81 +}
   58.82 +
   58.83 +void dma_write(uint16_t addr, uint8_t val)
   58.84 +{
   58.85 +//        printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc);
   58.86 +        dmaregs[addr&0xF]=val;
   58.87 +        switch (addr&0xF)
   58.88 +        {
   58.89 +                case 0: case 2: case 4: case 6: /*Address registers*/
   58.90 +                dma.wp^=1;
   58.91 +                if (dma.wp) dma.ab[(addr>>1)&3]=(dma.ab[(addr>>1)&3]&0xFF00)|val;
   58.92 +                else        dma.ab[(addr>>1)&3]=(dma.ab[(addr>>1)&3]&0xFF)|(val<<8);
   58.93 +                dma.ac[(addr>>1)&3]=dma.ab[(addr>>1)&3];
   58.94 +                dmaon[(addr>>1)&3]=1;
   58.95 +//                printf("DMA addr %i now %04X\n",(addr>>1)&3,dma.ac[(addr>>1)&3]);
   58.96 +                return;
   58.97 +                case 1: case 3: case 5: case 7: /*Count registers*/
   58.98 +                dma.wp^=1;
   58.99 +                if (dma.wp) dma.cb[(addr>>1)&3]=(dma.cb[(addr>>1)&3]&0xFF00)|val;
  58.100 +                else        dma.cb[(addr>>1)&3]=(dma.cb[(addr>>1)&3]&0xFF)|(val<<8);
  58.101 +                dma.cc[(addr>>1)&3]=dma.cb[(addr>>1)&3];
  58.102 +                dmaon[(addr>>1)&3]=1;
  58.103 +//                printf("DMA count %i now %04X\n",(addr>>1)&3,dma.cc[(addr>>1)&3]);
  58.104 +                return;
  58.105 +                case 8: /*Control register*/
  58.106 +                dma.command = val;
  58.107 +                return;
  58.108 +                case 0xA: /*Mask*/
  58.109 +                if (val&4) dma.m|=(1<<(val&3));
  58.110 +                else       dma.m&=~(1<<(val&3));
  58.111 +                return;
  58.112 +                case 0xB: /*Mode*/
  58.113 +                dma.mode[val&3]=val;
  58.114 +                return;
  58.115 +                case 0xC: /*Clear FF*/
  58.116 +                dma.wp=0;
  58.117 +                return;
  58.118 +                case 0xD: /*Master clear*/
  58.119 +                dma.wp=0;
  58.120 +                dma.m=0xF;
  58.121 +                return;
  58.122 +                case 0xF: /*Mask write*/
  58.123 +                dma.m=val&0xF;
  58.124 +                return;
  58.125 +        }
  58.126 +}
  58.127 +
  58.128 +uint8_t dma16_read(uint16_t addr)
  58.129 +{
  58.130 +        uint8_t temp;
  58.131 +//        printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
  58.132 +        addr>>=1;
  58.133 +        switch (addr&0xF)
  58.134 +        {
  58.135 +                case 0:
  58.136 +                if (((dma16.mode[0]>>2)&3)==2)
  58.137 +                {
  58.138 +                        dma16.ac[0]++;
  58.139 +                        dma16.cc[0]--;
  58.140 +                        if (dma16.cc[0]<0)
  58.141 +                        {
  58.142 +                                dma16.ac[0]=dma16.ab[0];
  58.143 +                                dma16.cc[0]=dma16.cb[0];
  58.144 +                        }
  58.145 +                }
  58.146 +                case 2: case 4: case 6: /*Address registers*/
  58.147 +                dma16.wp^=1;
  58.148 +                if (dma16.wp) return dma16.ac[(addr>>1)&3]&0xFF;
  58.149 +                return dma16.ac[(addr>>1)&3]>>8;
  58.150 +                case 1: case 3: case 5: case 7: /*Count registers*/
  58.151 +                dma16.wp^=1;
  58.152 +//                printf("Read %04X\n",dma16.cc[1]);
  58.153 +                if (dma16.wp) temp=dma16.cc[(addr>>1)&3]&0xFF;
  58.154 +                else        temp=dma16.cc[(addr>>1)&3]>>8;
  58.155 +//                printf("%02X\n",temp);
  58.156 +                return temp;
  58.157 +                case 8: /*Status register*/
  58.158 +                temp=dma16.stat;
  58.159 +                dma16.stat=0;
  58.160 +                return temp|1;
  58.161 +        }
  58.162 +        return dma16regs[addr&0xF];
  58.163 +}
  58.164 +
  58.165 +void dma16_write(uint16_t addr, uint8_t val)
  58.166 +{
  58.167 +//        printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc);
  58.168 +        addr>>=1;
  58.169 +        dma16regs[addr&0xF]=val;
  58.170 +        switch (addr&0xF)
  58.171 +        {
  58.172 +                case 0: case 2: case 4: case 6: /*Address registers*/
  58.173 +                dma16.wp^=1;
  58.174 +                if (dma16.wp) dma16.ab[(addr>>1)&3]=(dma16.ab[(addr>>1)&3]&0xFF00)|val;
  58.175 +                else        dma16.ab[(addr>>1)&3]=(dma16.ab[(addr>>1)&3]&0xFF)|(val<<8);
  58.176 +                dma16.ac[(addr>>1)&3]=dma16.ab[(addr>>1)&3];
  58.177 +                dma16on[(addr>>1)&3]=1;
  58.178 +//                printf("dma16 addr %i now %04X\n",(addr>>1)&3,dma16.ac[(addr>>1)&3]);
  58.179 +                return;
  58.180 +                case 1: case 3: case 5: case 7: /*Count registers*/
  58.181 +                dma16.wp^=1;
  58.182 +                if (dma16.wp) dma16.cb[(addr>>1)&3]=(dma16.cb[(addr>>1)&3]&0xFF00)|val;
  58.183 +                else        dma16.cb[(addr>>1)&3]=(dma16.cb[(addr>>1)&3]&0xFF)|(val<<8);
  58.184 +                dma16.cc[(addr>>1)&3]=dma16.cb[(addr>>1)&3];
  58.185 +                dma16on[(addr>>1)&3]=1;
  58.186 +//                printf("dma16 count %i now %04X\n",(addr>>1)&3,dma16.cc[(addr>>1)&3]);
  58.187 +                return;
  58.188 +                case 8: /*Control register*/
  58.189 +                return;
  58.190 +                case 0xA: /*Mask*/
  58.191 +                if (val&4) dma16.m|=(1<<(val&3));
  58.192 +                else       dma16.m&=~(1<<(val&3));
  58.193 +                return;
  58.194 +                case 0xB: /*Mode*/
  58.195 +                dma16.mode[val&3]=val;
  58.196 +                return;
  58.197 +                case 0xC: /*Clear FF*/
  58.198 +                dma16.wp=0;
  58.199 +                return;
  58.200 +                case 0xD: /*Master clear*/
  58.201 +                dma16.wp=0;
  58.202 +                dma16.m=0xF;
  58.203 +                return;
  58.204 +                case 0xF: /*Mask write*/
  58.205 +                dma16.m=val&0xF;
  58.206 +                return;
  58.207 +        }
  58.208 +}
  58.209 +
  58.210 +uint8_t dmapages[16];
  58.211 +static int primed = 0;
  58.212 +void dma_page_write(uint16_t addr, uint8_t val)
  58.213 +{
  58.214 +        if (!(addr&0xF))
  58.215 +        {
  58.216 +//                printf("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc);
  58.217 +//                if (val==0x29 && pc==0xD25) output=1;
  58.218 +        }
  58.219 +        dmapages[addr&0xF]=val;
  58.220 +        switch (addr&0xF)
  58.221 +        {
  58.222 +                case 1:
  58.223 +                dma.page[2]=(AT)?val:val&0xF;
  58.224 +                break;
  58.225 +                case 2:
  58.226 +                dma.page[3]=(AT)?val:val&0xF;
  58.227 +                break;
  58.228 +                case 3:
  58.229 +                dma.page[1]=(AT)?val:val&0xF;
  58.230 +//                pclog("DMA1 page %02X\n",val);
  58.231 +                break;
  58.232 +                case 0xB:
  58.233 +                dma16.page[1]=val;
  58.234 +                break;
  58.235 +        }
  58.236 +//        printf("Page write %04X %02X\n",addr,val);
  58.237 +}
  58.238 +
  58.239 +uint8_t dma_page_read(uint16_t addr)
  58.240 +{
  58.241 +        return dmapages[addr&0xF];
  58.242 +}
  58.243 +
  58.244 +void dma_init()
  58.245 +{
  58.246 +        io_sethandler(0x0000, 0x0010, dma_read,      NULL, NULL, dma_write,      NULL, NULL);
  58.247 +        io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL);
  58.248 +}
  58.249 +
  58.250 +void dma16_init()
  58.251 +{
  58.252 +        io_sethandler(0x00C0, 0x0020, dma16_read,    NULL, NULL, dma16_write,    NULL, NULL);
  58.253 +        io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL);
  58.254 +}
  58.255 +
  58.256 +
  58.257 +uint8_t _dma_read(uint32_t addr)
  58.258 +{
  58.259 +        switch (addr&0xFFFF8000)
  58.260 +        {
  58.261 +                case 0xA0000: case 0xA8000:
  58.262 +                return video_read_a000(addr);
  58.263 +                case 0xB0000:
  58.264 +                return video_read_b000(addr);
  58.265 +                case 0xB8000:
  58.266 +                return video_read_b800(addr);
  58.267 +        }
  58.268 +        if (isram[addr>>16]) return ram[addr];
  58.269 +        return 0xff;
  58.270 +}
  58.271 +
  58.272 +void _dma_write(uint32_t addr, uint8_t val)
  58.273 +{
  58.274 +        switch (addr&0xFFFF8000)
  58.275 +        {
  58.276 +                case 0xA0000: case 0xA8000:
  58.277 +                video_write_a000(addr,val);
  58.278 +                return;
  58.279 +                case 0xB0000:
  58.280 +                video_write_b000(addr,val);
  58.281 +                return;
  58.282 +                case 0xB8000:
  58.283 +                video_write_b800(addr,val);
  58.284 +                return;
  58.285 +                case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000:
  58.286 +                case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000:
  58.287 +                return;
  58.288 +        }
  58.289 +        if (isram[addr>>16]) ram[addr]=val;
  58.290 +}
  58.291 +/*void writedma2(uint8_t val)
  58.292 +{
  58.293 +//        printf("Write to %05X %02X %i\n",(dma.page[2]<<16)+dma.ac[2],val,dma.m&4);
  58.294 +        if (!(dma.m&4))
  58.295 +        {
  58.296 +                ram[((dma.page[2]<<16)+dma.ac[2])&rammask]=val;
  58.297 +                dma.ac[2]++;
  58.298 +                dma.cc[2]--;
  58.299 +                if (dma.cc[2]==-1)
  58.300 +                {
  58.301 +                        dma.m|=4;
  58.302 +                        dma.stat|=4;
  58.303 +                }
  58.304 +        }
  58.305 +}*/
  58.306 +
  58.307 +uint8_t readdma2()
  58.308 +{
  58.309 +        uint8_t temp;
  58.310 +//        pclog("Read DMA2 %02X %02X\n",dma.m,dma.mode[2]);
  58.311 +        if (dma.m&4)
  58.312 +        {
  58.313 +                fdc_abort();
  58.314 +                return 0xFF;
  58.315 +        }
  58.316 +        if ((dma.mode[2]&0xC)!=8)
  58.317 +        {
  58.318 +                fdc_abort();
  58.319 +                return 0xFF;
  58.320 +        }
  58.321 +        temp=_dma_read((dma.ac[2]+(dma.page[2]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
  58.322 +//        pclog("DMA2 %02X %05X\n",temp,(dma.ac[2]+(dma.page[2]<<16))&rammask);
  58.323 +        if (dma.mode[2]&0x20) dma.ac[2]--;
  58.324 +        else                  dma.ac[2]++;
  58.325 +        dma.cc[2]--;
  58.326 +        if (!dma.cc[2] && (dma.mode[2]&0x10))
  58.327 +        {
  58.328 +                dma.cc[2]=dma.cb[2]+1;
  58.329 +                dma.ac[2]=dma.ab[2];
  58.330 +        }
  58.331 +        else if (dma.cc[2]<=-1)
  58.332 +           dma.m|=4;
  58.333 +        return temp;
  58.334 +}
  58.335 +
  58.336 +void writedma2(uint8_t temp)
  58.337 +{
  58.338 +//        pclog("Write DMA2 %02X %02X %04X\n",dma.m,dma.mode[2],dma.cc[2]);
  58.339 +        if (dma.m&4)
  58.340 +        {
  58.341 +                fdc_abort();
  58.342 +                return;
  58.343 +        }
  58.344 +        if ((dma.mode[2]&0xC)!=4)
  58.345 +        {
  58.346 +                fdc_abort();
  58.347 +                return;
  58.348 +        }
  58.349 +//        pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp);
  58.350 +//        ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp;
  58.351 +        _dma_write((dma.ac[2]+(dma.page[2]<<16))&rammask,temp);
  58.352 +        if (dma.mode[2]&0x20) dma.ac[2]--;
  58.353 +        else                  dma.ac[2]++;
  58.354 +        dma.cc[2]--;
  58.355 +        if (!dma.cc[2] && (dma.mode[2]&0x10))
  58.356 +        {
  58.357 +                dma.cc[2]=dma.cb[2]+1;
  58.358 +                dma.ac[2]=dma.ab[2];
  58.359 +        }
  58.360 +        else if (dma.cc[2]<=-1)
  58.361 +        {
  58.362 +//                pclog("Reached TC\n");
  58.363 +                fdc_abort();
  58.364 +                dma.m|=4;
  58.365 +        }
  58.366 +}
  58.367 +
  58.368 +uint8_t readdma1()
  58.369 +{
  58.370 +        uint8_t temp=0;
  58.371 +        /*if ((dma.ac[1]+(dma.page[1]<<16))<0x800000)  */temp=ram[(dma.ac[1]+(dma.page[1]<<16))&rammask];
  58.372 +//        printf("Read DMA1 from %05X %02X %04X %02X %i\n",dma.ac[1]+(dma.page[1]<<16),dma.mode[1],dma.cc[1],temp,dmaon[1]);
  58.373 +        if (!dmaon[1])
  58.374 +        {
  58.375 +//                printf("DMA off!\n");
  58.376 +                return temp;
  58.377 +        }
  58.378 +        dma.ac[1]++;
  58.379 +        dma.cc[1]--;
  58.380 +        if (dma.cc[1]<=-1 && (dma.mode[1]&0x10))
  58.381 +        {
  58.382 +                dma.cc[1]=dma.cb[1];
  58.383 +                dma.ac[1]=dma.ab[1];
  58.384 +        }
  58.385 +        else if (dma.cc[1]<=-1)
  58.386 +           dmaon[1]=0;
  58.387 +        return temp;
  58.388 +}
  58.389 +
  58.390 +uint16_t readdma5()
  58.391 +{
  58.392 +        uint16_t temp=0;
  58.393 +//        pclog("Read DMA5 %i %04X\n",dma16on[1],dma16.cc[1]);
  58.394 +        /*if ((dma16.ac[1]+(dma16.page[1]<<16))<0x800000)  */temp=ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16))&rammask]|(ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16)+1)&rammask]<<8);
  58.395 +        //readmemwl(dma16.ac[1]+(dma16.page[1]<<16));
  58.396 +//        printf("Read DMA1 from %05X %05X %02X %04X\n",dma.ac[1]+(dma.page[1]<<16),(dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16),dma16.mode[1],temp);
  58.397 +        if (!dma16on[1])
  58.398 +        {
  58.399 +//                printf("DMA off!\n");
  58.400 +                return temp;
  58.401 +        }
  58.402 +        dma16.ac[1]++;
  58.403 +        dma16.cc[1]--;
  58.404 +        if (dma16.cc[1]<=-1 && (dma16.mode[1]&0x10))
  58.405 +        {
  58.406 +                dma16.cc[1]=dma16.cb[1];
  58.407 +                dma16.ac[1]=dma16.ab[1];
  58.408 +        }
  58.409 +        else if (dma16.cc[1]<=-1)
  58.410 +           dma16on[1]=0;
  58.411 +        return temp;
  58.412 +}
  58.413 +
  58.414 +void writedma1(uint8_t temp)
  58.415 +{
  58.416 +        if (!dmaon[1]) return;
  58.417 +        ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]=temp;
  58.418 +        dma.ac[1]++;
  58.419 +        dma.cc[1]--;
  58.420 +        if (!dma.cc[1] && (dma.mode[1]&0x10))
  58.421 +        {
  58.422 +                dma.cc[1]=dma.cb[1]+1;
  58.423 +                dma.ac[1]=dma.ab[1];
  58.424 +        }
  58.425 +        else if (dma.cc[1]<=-1)
  58.426 +           dmaon[1]=0;
  58.427 +}
  58.428 +void writedma5(uint16_t temp)
  58.429 +{
  58.430 +        if (!dma16on[1]) return;
  58.431 +        ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16))&rammask]=temp;
  58.432 +        ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16)+1)&rammask]=temp>>8;
  58.433 +
  58.434 +        dma16.ac[1]++;
  58.435 +        dma16.cc[1]--;
  58.436 +        if (dma16.cc[1]<=-1 && (dma16.mode[1]&0x10))
  58.437 +        {
  58.438 +                dma16.cc[1]=dma16.cb[1];
  58.439 +                dma16.ac[1]=dma16.ab[1];
  58.440 +        }
  58.441 +        else if (dma16.cc[1]<=-1)
  58.442 +           dma16on[1]=0;
  58.443 +}
  58.444 +
  58.445 +int readdma3()
  58.446 +{
  58.447 +        uint8_t temp=ram[((dma.page[3]<<16)+dma.ac[3])&rammask];
  58.448 +        if (dma.m&8)
  58.449 +        {
  58.450 +                return -1;
  58.451 +        }
  58.452 +//        printf("Read DMA 3 - %02X %05X %i\n",temp,(dma.page[3]<<16)+dma.ac[3],dma.cc[3]);
  58.453 +        if (!(dma.m&8))
  58.454 +        {
  58.455 +                dma.ac[3]++;
  58.456 +                dma.cc[3]--;
  58.457 +                if (dma.cc[3]==-1)
  58.458 +                {
  58.459 +                        dma.m|=8;
  58.460 +                        dma.stat|=8;
  58.461 +                }
  58.462 +        }
  58.463 +        return temp;
  58.464 +}
  58.465 +void readdma0()
  58.466 +{
  58.467 +        if (AT) ppi.pb^=0x10;        
  58.468 +        if (dma.command & 4) return;
  58.469 +//        if (AMSTRAD) return;
  58.470 +        refreshread();
  58.471 +//        pclog("Read refresh %02X %02X %04X %04X\n",dma.m,dma.mode[0],dma.ac[0],dma.cc[0]);
  58.472 +        if (dma.m&1) return;
  58.473 +//        readmembl((dma.page[0]<<16)+dma.ac[0]);
  58.474 +//        if (!(dma.m&1))
  58.475 +//        {
  58.476 +                dma.ac[0]+=2;
  58.477 +                dma.cc[0]--;
  58.478 +                if (dma.cc[0]==-1)
  58.479 +                {
  58.480 +                        dma.stat|=1;
  58.481 +                        dma.ac[0]=dma.ab[0];
  58.482 +                        dma.cc[0]=dma.cb[0];
  58.483 +                }
  58.484 +//        }
  58.485 +//        ppi.pb^=0x10;
  58.486 +}
  58.487 +
  58.488 +void dumpdma()
  58.489 +{
  58.490 +        printf("Address : %04X %04X %04X %04X\n",dma.ac[0],dma.ac[1],dma.ac[2],dma.ac[3]);
  58.491 +        printf("Count   : %04X %04X %04X %04X\n",dma.cc[0],dma.cc[1],dma.cc[2],dma.cc[3]);
  58.492 +        printf("Mask %02X Stat %02X\n",dma.m,dma.stat);
  58.493 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/src/dma.h	Sun Apr 21 14:54:35 2013 +0100
    59.3 @@ -0,0 +1,3 @@
    59.4 +void dma_init();
    59.5 +void dma16_init();
    59.6 +void dma_reset();
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/src/ega.c	Sun Apr 21 14:54:35 2013 +0100
    60.3 @@ -0,0 +1,298 @@
    60.4 +#include "ibm.h"
    60.5 +#include "video.h"
    60.6 +
    60.7 +void doblit();
    60.8 +
    60.9 +int egareads=0,egawrites=0;
   60.10 +int framecount=0;
   60.11 +int changeframecount=2;
   60.12 +
   60.13 +void redotextlookup();
   60.14 +int output;
   60.15 +int svgaon=0;
   60.16 +uint32_t svgarbank,svgawbank;
   60.17 +uint8_t svgaseg,svgaseg2;
   60.18 +uint8_t svga3d8;
   60.19 +
   60.20 +uint8_t oldvram=0;
   60.21 +int frames;
   60.22 +int incga=1;
   60.23 +int hsync;
   60.24 +uint8_t cgastat;
   60.25 +
   60.26 +uint8_t gdcreg[16];
   60.27 +int gdcaddr;
   60.28 +uint8_t attrregs[32];
   60.29 +int attraddr,attrff=0;
   60.30 +uint8_t ega3c2;
   60.31 +
   60.32 +uint8_t rotatevga[8][256];
   60.33 +uint8_t writemask,charset;
   60.34 +int writemode,readmode,readplane,chain4;
   60.35 +uint8_t colourcompare,colournocare;
   60.36 +uint8_t la,lb,lc,ld;
   60.37 +
   60.38 +uint8_t *vram;
   60.39 +
   60.40 +int egares;
   60.41 +
   60.42 +uint8_t seqregs[32];
   60.43 +int seqaddr;
   60.44 +
   60.45 +uint8_t oak_regs[32];
   60.46 +int oak_index;
   60.47 +
   60.48 +
   60.49 +extern int egaswitchread,egaswitches;
   60.50 +/*For VGA non-interlace colour, ID bits should be 1 1 0 or 6*/
   60.51 +int vres=0;
   60.52 +
   60.53 +PALETTE vgapal;
   60.54 +uint32_t *pallook,pallook16[256],pallook64[256],pallook256[256];
   60.55 +int dacread,dacwrite,dacpos=0;
   60.56 +int palchange=1;
   60.57 +
   60.58 +int fullchange;
   60.59 +
   60.60 +float dispontime,dispofftime,disptime;
   60.61 +
   60.62 +int ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,ega_rowoffset;
   60.63 +int vidclock;
   60.64 +float cpuclock;
   60.65 +
   60.66 +int bpp;
   60.67 +
   60.68 +uint32_t vrammask;
   60.69 +
   60.70 +uint8_t changedvram[(8192*1024)/1024];
   60.71 +
   60.72 +
   60.73 +int charseta,charsetb;
   60.74 +
   60.75 +int egapal[16];
   60.76 +
   60.77 +int displine;
   60.78 +
   60.79 +int rowdbl=0;
   60.80 +int scrblank=0;
   60.81 +
   60.82 +
   60.83 +
   60.84 +
   60.85 +uint8_t edatlookup[4][4];
   60.86 +
   60.87 +uint32_t textlookup[256][2][16][16];
   60.88 +
   60.89 +/*void redotextlookup()
   60.90 +{
   60.91 +        int c,d,e;
   60.92 +        uint32_t temp;
   60.93 +        int coffset=(VGA)?0:64;
   60.94 +        for (c=0;c<256;c++)
   60.95 +        {
   60.96 +                for (d=0;d<16;d++)
   60.97 +                {
   60.98 +//                        printf("ATTR %i=%02X+%02X\n",d,attrregs[d],coffset);
   60.99 +                        for (e=0;e<16;e++)
  60.100 +                        {
  60.101 +                                temp=0;
  60.102 +                                if (c&0x80) temp|=(attrregs[d]+coffset);
  60.103 +                                else        temp|=(attrregs[e]+coffset);
  60.104 +                                if (c&0x40) temp|=(attrregs[d]+coffset)<<8;
  60.105 +                                else        temp|=(attrregs[e]+coffset)<<8;
  60.106 +                                if (c&0x20) temp|=(attrregs[d]+coffset)<<16;
  60.107 +                                else        temp|=(attrregs[e]+coffset)<<16;
  60.108 +                                if (c&0x10) temp|=(attrregs[d]+coffset)<<24;
  60.109 +                                else        temp|=(attrregs[e]+coffset)<<24;
  60.110 +//                                if (c==0x5) printf("%08X %i %i %02X %02X\n",temp,d,e,attrregs[d],attrregs[e]);
  60.111 +                                textlookup[c][0][d][e]=temp;
  60.112 +                                temp=0;
  60.113 +                                if (c&0x08) temp|=(attrregs[d]+coffset);
  60.114 +                                else        temp|=(attrregs[e]+coffset);
  60.115 +                                if (c&0x04) temp|=(attrregs[d]+coffset)<<8;
  60.116 +                                else        temp|=(attrregs[e]+coffset)<<8;
  60.117 +                                if (c&0x02) temp|=(attrregs[d]+coffset)<<16;
  60.118 +                                else        temp|=(attrregs[e]+coffset)<<16;
  60.119 +                                if (c&0x01) temp|=(attrregs[d]+coffset)<<24;
  60.120 +                                else        temp|=(attrregs[e]+coffset)<<24;
  60.121 +                                textlookup[c][1][d][e]=temp;
  60.122 +                        }
  60.123 +                }
  60.124 +        }
  60.125 +}*/
  60.126 +
  60.127 +void initega()
  60.128 +{
  60.129 +        int c,d,e;
  60.130 +        bpp=8;
  60.131 +        for (c=0;c<256;c++)
  60.132 +        {
  60.133 +                e=c;
  60.134 +                for (d=0;d<8;d++)
  60.135 +                {
  60.136 +                        rotatevga[d][c]=e;
  60.137 +                        e=(e>>1)|((e&1)?0x80:0);
  60.138 +                }
  60.139 +        }
  60.140 +        crtc[0xC]=crtc[0xD]=0;
  60.141 +        if (romset==ROM_PC1640 || romset==ROM_PC1512) incga=1;
  60.142 +        else                    incga=0;
  60.143 +        for (c=0;c<4;c++)
  60.144 +        {
  60.145 +                for (d=0;d<4;d++)
  60.146 +                {
  60.147 +                        edatlookup[c][d]=0;
  60.148 +                        if (c&1) edatlookup[c][d]|=1;
  60.149 +                        if (d&1) edatlookup[c][d]|=2;
  60.150 +                        if (c&2) edatlookup[c][d]|=0x10;
  60.151 +                        if (d&2) edatlookup[c][d]|=0x20;
  60.152 +//                        printf("Edat %i,%i now %02X\n",c,d,edatlookup[c][d]);
  60.153 +                }
  60.154 +        }
  60.155 +        /*redotextlookup();*/
  60.156 +        for (c=0;c<256;c++)
  60.157 +        {
  60.158 +                pallook64[c]=makecol32(((c>>2)&1)*0xAA,((c>>1)&1)*0xAA,(c&1)*0xAA);
  60.159 +                pallook64[c]+=makecol32(((c>>5)&1)*0x55,((c>>4)&1)*0x55,((c>>3)&1)*0x55);
  60.160 +                pallook16[c]=makecol32(((c>>2)&1)*0xAA,((c>>1)&1)*0xAA,(c&1)*0xAA);
  60.161 +                pallook16[c]+=makecol32(((c>>4)&1)*0x55,((c>>4)&1)*0x55,((c>>4)&1)*0x55);
  60.162 +                if ((c&0x17)==6) pallook16[c]=makecol32(0xAA,0x55,0);
  60.163 +//                printf("%03i %08X\n",c,pallook[c]);
  60.164 +        }
  60.165 +        pallook=pallook16;
  60.166 +        seqregs[0xC]=0x20;
  60.167 +        vrammask=(ET4000)?0xFFFFF:0x1FFFFF;
  60.168 +//        writeega_func=writeega;
  60.169 +        gdcreg[6]=8;
  60.170 +        gdcreg[8]=0xFF;
  60.171 +        writemode=0;
  60.172 +        chain4=0;
  60.173 +        writemask=3;
  60.174 +        
  60.175 +        et4k_b8000=0;
  60.176 +        
  60.177 +        svgarbank=svgawbank=0;
  60.178 +}
  60.179 +uint32_t egabase,egaoffset;
  60.180 +
  60.181 +void cacheega()
  60.182 +{
  60.183 +        egabase=(crtc[0xC]<<8)|crtc[0xD];
  60.184 +        if (ET4000 || ET4000W32 || TRIDENT)
  60.185 +           egabase|=((crtc[0x33]&3)<<18);
  60.186 +//        printf("EGABASE %05X\n",egabase);
  60.187 +//        egaoffset=8-((attrregs[0x13])&7);
  60.188 +//        printf("Cache base!\n");
  60.189 +}
  60.190 +void cacheega2()
  60.191 +{
  60.192 +//        egabase=(crtc[0xC]<<8)|crtc[0xD];
  60.193 +        if (gdcreg[5]&0x40) egaoffset=8-(((attrregs[0x13])&7)>>1);
  60.194 +        else                egaoffset=8-((attrregs[0x13])&7);
  60.195 +//        printf("Cache offset!\n");
  60.196 +}
  60.197 +
  60.198 +int olddisplines,oldxsize;
  60.199 +
  60.200 +int oldreadflash;
  60.201 +int oldegaaddr,oldegasplit;
  60.202 +
  60.203 +int vc,sc;
  60.204 +int egadispon=0;
  60.205 +int linepos;
  60.206 +int displine;
  60.207 +uint32_t ma,maback,ca;
  60.208 +int firstline,lastline;
  60.209 +int xsize,ysize;
  60.210 +int scrollcache;
  60.211 +int con,cursoron,cgablink;
  60.212 +
  60.213 +BITMAP *buffer,*vbuf,*buffer32;
  60.214 +
  60.215 +int linecountff=0;
  60.216 +
  60.217 +void dumpegaregs()
  60.218 +{
  60.219 +        int c;
  60.220 +        printf("CRTC :");
  60.221 +        for (c=0;c<0x20;c++) printf(" %02X",crtc[c]);
  60.222 +        printf("\n");
  60.223 +        printf(" EXT :");
  60.224 +        for (c=0;c<0x20;c++) printf(" %02X",crtc[c+32]);
  60.225 +        printf("\n");
  60.226 +        printf(" EXT2:");
  60.227 +        for (c=0;c<0x20;c++) printf(" %02X",crtc[c+64]);
  60.228 +        printf("\n");
  60.229 +        printf("SEQ  :");
  60.230 +        for (c=0;c<0x10;c++) printf(" %02X",seqregs[c]);
  60.231 +        printf("\n");
  60.232 +        printf(" EXT :");
  60.233 +        for (c=0;c<0x10;c++) printf(" %02X",seqregs[c + 0x10]);
  60.234 +        printf("\n");
  60.235 +        printf("ATTR :");
  60.236 +        for (c=0;c<0x20;c++) printf(" %02X",attrregs[c]);
  60.237 +        printf("\n");
  60.238 +        printf("GDC  :");
  60.239 +        for (c=0;c<0x10;c++) printf(" %02X",gdcreg[c]);
  60.240 +        printf("\n");
  60.241 +//        printf("OLD CTRL2 = %02X  NEW CTRL2 = %02X  DAC = %02X  3C2 = %02X\n",tridentoldctrl2,tridentnewctrl2,tridentdac,ega3c2);
  60.242 +        printf("BPP = %02X\n",bpp);
  60.243 +}
  60.244 +
  60.245 +int oddeven;
  60.246 +
  60.247 +int wx,wy;
  60.248 +int vslines;
  60.249 +
  60.250 +int frames = 0;
  60.251 +
  60.252 +void doblit()
  60.253 +{
  60.254 +        startblit();
  60.255 +        if ((wx!=xsize || wy!=ysize) && !vid_resize)
  60.256 +        {
  60.257 +                xsize=wx;
  60.258 +                ysize=wy+1;
  60.259 +                if (xsize<64) xsize=656;
  60.260 +                if (ysize<32) ysize=200;
  60.261 +                if (vres) updatewindowsize(xsize,ysize<<1);
  60.262 +                else      updatewindowsize(xsize,ysize);
  60.263 +        }
  60.264 +        video_blit_memtoscreen(32, 0, 0, ysize, xsize, ysize);
  60.265 +        if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
  60.266 +        endblit();
  60.267 +        frames++;
  60.268 +}
  60.269 +
  60.270 +int ega_getdepth()
  60.271 +{
  60.272 +        if (!(gdcreg[6]&1)) return 0;
  60.273 +        switch (gdcreg[5]&0x60)
  60.274 +        {
  60.275 +                case 0x00:
  60.276 +                return 4;
  60.277 +                case 0x20:
  60.278 +                return 2;
  60.279 +                case 0x40: case 0x60:
  60.280 +                if (TRIDENT || ET4000W32) return bpp;
  60.281 +                return 8;
  60.282 +        }
  60.283 +}
  60.284 +
  60.285 +int ega_getx()
  60.286 +{
  60.287 +        int x;
  60.288 +        if (!(gdcreg[6]&1)) return (crtc[1]+1);
  60.289 +        if ((attrregs[0x10]&0x40) && !(tridentoldctrl2&0x10)) x=(crtc[1]+1)*4;
  60.290 +        else                                                  x=(crtc[1]+1)*8;
  60.291 +        if (TRIDENT && (bpp==15 || bpp==16)) x>>=1;
  60.292 +        if (TRIDENT && bpp==24) x=(x<<1)/3;
  60.293 +        return x;
  60.294 +}
  60.295 +
  60.296 +int ega_gety()
  60.297 +{
  60.298 +        if (crtc[0x1E]&4) return (ega_dispend/((crtc[9]&31)+1))<<1;
  60.299 +        if (crtc[9]&0x80) return (ega_dispend/((crtc[9]&31)+1))>>1;
  60.300 +        return ega_dispend/((crtc[9]&31)+1);
  60.301 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/src/fdc.c	Sun Apr 21 14:54:35 2013 +0100
    61.3 @@ -0,0 +1,806 @@
    61.4 +#include <stdio.h>
    61.5 +#include <string.h>
    61.6 +#include "ibm.h"
    61.7 +
    61.8 +void fdc_poll();
    61.9 +int timetolive;
   61.10 +int TRACKS[2] = {80, 80};
   61.11 +int SECTORS[2]={9,9};
   61.12 +int SIDES[2]={2,2};
   61.13 +//#define SECTORS 9
   61.14 +int output;
   61.15 +int lastbyte=0;
   61.16 +uint8_t disc[2][2][80][36][512];
   61.17 +uint8_t disc_3f7;
   61.18 +
   61.19 +int discchanged[2];
   61.20 +int discmodified[2];
   61.21 +int discrate[2];
   61.22 +
   61.23 +void loaddisc(int d, char *fn)
   61.24 +{
   61.25 +        FILE *f=fopen(fn,"rb");
   61.26 +        int h,t,s,b;
   61.27 +        if (!f)
   61.28 +        {
   61.29 +                SECTORS[d]=9; SIDES[d]=1;
   61.30 +                driveempty[d]=1; discrate[d]=4;
   61.31 +                return;
   61.32 +        }
   61.33 +        driveempty[d]=0;
   61.34 +        SIDES[d]=2;
   61.35 +        fseek(f,-1,SEEK_END);
   61.36 +        if (ftell(f)<=(160*1024))       { SECTORS[d]=8;  TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
   61.37 +        else if (ftell(f)<=(180*1024))  { SECTORS[d]=9;  TRACKS[d] = 40; SIDES[d]=1; discrate[d]=2; }
   61.38 +        else if (ftell(f)<=(320*1024))  { SECTORS[d]=8;  TRACKS[d] = 40; discrate[d]=2; }
   61.39 +        else if (ftell(f)<(1024*1024))  { SECTORS[d]=9;  TRACKS[d] = 80; discrate[d]=2; } /*Double density*/
   61.40 +        else if (ftell(f)<(0x1A4000-1)) { SECTORS[d]=18; TRACKS[d] = 80; discrate[d]=0; } /*High density (not supported by Tandy 1000)*/
   61.41 +        else if (ftell(f) == 1884159)   { SECTORS[d]=23; TRACKS[d] = 80; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
   61.42 +        else if (ftell(f) == 1763327)   { SECTORS[d]=21; TRACKS[d] = 82; discrate[d]=0; } /*XDF format - used by OS/2 Warp*/
   61.43 +        else if (ftell(f)<(2048*1024))  { SECTORS[d]=21; TRACKS[d] = 80; discrate[d]=0; } /*DMF format - used by Windows 95*/
   61.44 +        else                            { SECTORS[d]=36; TRACKS[d] = 80; discrate[d]=3; } /*E density (not supported by anything)*/
   61.45 +        printf("Drive %c: has %i sectors and %i sides and is %i bytes long\n",'A'+d,SECTORS[0],SIDES[0],ftell(f));
   61.46 +        fseek(f,0,SEEK_SET);
   61.47 +        for (t=0;t<80;t++)
   61.48 +        {
   61.49 +                for (h=0;h<SIDES[d];h++)
   61.50 +                {
   61.51 +                        for (s=0;s<SECTORS[d];s++)
   61.52 +                        {
   61.53 +                                for (b=0;b<512;b++)
   61.54 +                                {
   61.55 +                                        disc[d][h][t][s][b]=getc(f);
   61.56 +                                }
   61.57 +                        }
   61.58 +                }
   61.59 +        }
   61.60 +        fclose(f);
   61.61 +        discmodified[d]=0;
   61.62 +        strcpy(discfns[d],fn);
   61.63 +        discchanged[d]=1;
   61.64 +}
   61.65 +
   61.66 +void ejectdisc(int d)
   61.67 +{
   61.68 +        discfns[d][0]=0;
   61.69 +        SECTORS[d]=9; SIDES[d]=1;
   61.70 +        driveempty[d]=1; discrate[d]=4;
   61.71 +}
   61.72 +
   61.73 +void savedisc(int d)
   61.74 +{
   61.75 +        FILE *f;
   61.76 +        int h,t,s,b;
   61.77 +        if (!discmodified[d]) return;
   61.78 +        f=fopen(discfns[d],"wb");
   61.79 +        if (!f) return;
   61.80 +        printf("Save disc %c: %s %i %i\n",'A'+d,discfns[0],SIDES[0],SECTORS[0]);
   61.81 +        for (t=0;t<80;t++)
   61.82 +        {
   61.83 +                for (h=0;h<SIDES[d];h++)
   61.84 +                {
   61.85 +                        for (s=0;s<SECTORS[d];s++)
   61.86 +                        {
   61.87 +                                for (b=0;b<512;b++)
   61.88 +                                {
   61.89 +                                        putc(disc[d][h][t][s][b],f);
   61.90 +                                }
   61.91 +                        }
   61.92 +                }
   61.93 +        }
   61.94 +        fclose(f);
   61.95 +}
   61.96 +
   61.97 +int discint;
   61.98 +void fdc_reset()
   61.99 +{
  61.100 +        fdc.stat=0x80;
  61.101 +        fdc.pnum=fdc.ptot=0;
  61.102 +        fdc.st0=0xC0;
  61.103 +        fdc.lock = 0;
  61.104 +        fdc.head = 0;
  61.105 +        if (!AT)
  61.106 +           fdc.rate=2;
  61.107 +//        pclog("Reset FDC\n");
  61.108 +}
  61.109 +int ins;
  61.110 +
  61.111 +void fdc_write(uint16_t addr, uint8_t val)
  61.112 +{
  61.113 +        int c;
  61.114 +//        printf("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate);
  61.115 +        switch (addr&7)
  61.116 +        {
  61.117 +                case 1: return;
  61.118 +                case 2: /*DOR*/
  61.119 +//                if (val == 0xD && (cs >> 4) == 0xFC81600 && ins > 769619936) output = 3;
  61.120 +//                printf("DOR was %02X\n",fdc.dor);
  61.121 +                if (val&4)
  61.122 +                {
  61.123 +                        fdc.stat=0x80;
  61.124 +                        fdc.pnum=fdc.ptot=0;
  61.125 +                }
  61.126 +                if ((val&4) && !(fdc.dor&4))
  61.127 +                {
  61.128 +                        disctime=128;
  61.129 +                        discint=-1;
  61.130 +                        fdc_reset();
  61.131 +                }
  61.132 +                fdc.dor=val;
  61.133 +//                printf("DOR now %02X\n",val);
  61.134 +                return;
  61.135 +                case 4:
  61.136 +                if (val & 0x80)
  61.137 +                {
  61.138 +                        disctime=128;
  61.139 +                        discint=-1;
  61.140 +                        fdc_reset();
  61.141 +                }
  61.142 +                return;
  61.143 +                case 5: /*Command register*/
  61.144 +//                pclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot);
  61.145 +                if (fdc.pnum==fdc.ptot)
  61.146 +                {
  61.147 +                        fdc.command=val;
  61.148 +//                        printf("Starting FDC command %02X\n",fdc.command);
  61.149 +                        switch (fdc.command&0x1F)
  61.150 +                        {
  61.151 +                                case 2: /*Read track*/
  61.152 +//                                printf("Read track!\n");
  61.153 +                                fdc.pnum=0;
  61.154 +                                fdc.ptot=8;
  61.155 +                                fdc.stat=0x90;
  61.156 +                                fdc.pos=0;
  61.157 +                                break;
  61.158 +                                case 3: /*Specify*/
  61.159 +                                fdc.pnum=0;
  61.160 +                                fdc.ptot=2;
  61.161 +                                fdc.stat=0x90;
  61.162 +                                break;
  61.163 +                                case 4: /*Sense drive status*/
  61.164 +                                fdc.pnum=0;
  61.165 +                                fdc.ptot=1;
  61.166 +                                fdc.stat=0x90;
  61.167 +                                break;
  61.168 +                                case 5: /*Write data*/
  61.169 +//                                printf("Write data!\n");
  61.170 +                                fdc.pnum=0;
  61.171 +                                fdc.ptot=8;
  61.172 +                                fdc.stat=0x90;
  61.173 +                                fdc.pos=0;
  61.174 +                                readflash=1;
  61.175 +                                break;
  61.176 +                                case 6: /*Read data*/
  61.177 +                                fullspeed();
  61.178 +                                fdc.pnum=0;
  61.179 +                                fdc.ptot=8;
  61.180 +                                fdc.stat=0x90;
  61.181 +                                fdc.pos=0;
  61.182 +                                readflash=1;
  61.183 +                                break;
  61.184 +                                case 7: /*Recalibrate*/
  61.185 +                                fdc.pnum=0;
  61.186 +                                fdc.ptot=1;
  61.187 +                                fdc.stat=0x90;
  61.188 +                                break;
  61.189 +                                case 8: /*Sense interrupt status*/
  61.190 +//                                printf("Sense interrupt status %i\n",fdc.drive);
  61.191 +                                fdc.lastdrive = fdc.drive;
  61.192 +//                                fdc.stat = 0x10 | (fdc.stat & 0xf);
  61.193 +//                                disctime=1024;
  61.194 +                                discint = 8;
  61.195 +                                fdc.pos = 0;
  61.196 +                                fdc_poll();
  61.197 +                                break;
  61.198 +                                case 10: /*Read sector ID*/
  61.199 +                                fdc.pnum=0;
  61.200 +                                fdc.ptot=1;
  61.201 +                                fdc.stat=0x90;
  61.202 +                                fdc.pos=0;
  61.203 +                                break;
  61.204 +                                case 15: /*Seek*/
  61.205 +                                fdc.pnum=0;
  61.206 +                                fdc.ptot=2;
  61.207 +                                fdc.stat=0x90;
  61.208 +                                break;
  61.209 +                                case 0x0e: /*Dump registers*/
  61.210 +                                fdc.lastdrive = fdc.drive;
  61.211 +                                discint = 0x0e;
  61.212 +                                fdc.pos = 0;
  61.213 +                                fdc_poll();
  61.214 +                                break;
  61.215 +                                case 0x10: /*Get version*/
  61.216 +                                fdc.lastdrive = fdc.drive;
  61.217 +                                discint = 0x10;
  61.218 +                                fdc.pos = 0;
  61.219 +                                fdc_poll();
  61.220 +                                break;
  61.221 +                                case 0x12: /*Set perpendicular mode*/
  61.222 +                                fdc.pnum=0;
  61.223 +                                fdc.ptot=1;
  61.224 +                                fdc.stat=0x90;
  61.225 +                                fdc.pos=0;
  61.226 +                                break;
  61.227 +                                case 0x13: /*Configure*/
  61.228 +                                fdc.pnum=0;
  61.229 +                                fdc.ptot=3;
  61.230 +                                fdc.stat=0x90;
  61.231 +                                fdc.pos=0;
  61.232 +                                break;
  61.233 +                                case 0x14: /*Unlock*/
  61.234 +                                case 0x94: /*Lock*/
  61.235 +                                fdc.lastdrive = fdc.drive;
  61.236 +                                discint = fdc.command;
  61.237 +                                fdc.pos = 0;
  61.238 +                                fdc_poll();
  61.239 +                                break;
  61.240 +
  61.241 +                                case 0x18:
  61.242 +                                fdc.stat = 0x10;
  61.243 +                                discint  = 0xfc;
  61.244 +                                fdc_poll();
  61.245 +                                break;
  61.246 +
  61.247 +                                default:
  61.248 +                                pclog("Bad FDC command %02X\n",val);
  61.249 +//                                dumpregs();
  61.250 +//                                exit(-1);
  61.251 +                                fdc.stat=0x10;
  61.252 +                                discint=0xfc;
  61.253 +                                disctime=200;
  61.254 +                                break;
  61.255 +                        }
  61.256 +                }
  61.257 +                else
  61.258 +                {
  61.259 +                        fdc.params[fdc.pnum++]=val;
  61.260 +                        if (fdc.pnum==fdc.ptot)
  61.261 +                        {
  61.262 +//                                pclog("Got all params\n");
  61.263 +                                fdc.stat=0x30;
  61.264 +                                discint=fdc.command&0x1F;
  61.265 +                                disctime=1024;
  61.266 +                                fdc.drive=fdc.params[0]&1;
  61.267 +                                if (discint==2 || discint==5 || discint==6)
  61.268 +                                {
  61.269 +                                        fdc.track[fdc.drive]=fdc.params[1];
  61.270 +                                        fdc.head=fdc.params[2];
  61.271 +                                        fdc.sector=fdc.params[3];
  61.272 +                                        fdc.eot[fdc.drive] = fdc.params[4];
  61.273 +                                        if (!fdc.params[5])
  61.274 +                                        {
  61.275 +                                                fdc.params[5]=fdc.sector;
  61.276 +                                        }
  61.277 +                                        if (fdc.params[5]>SECTORS[fdc.drive]) fdc.params[5]=SECTORS[fdc.drive];
  61.278 +                                        if (driveempty[fdc.drive])
  61.279 +                                        {
  61.280 +//                                                pclog("Drive empty\n");
  61.281 +                                                discint=0xFE;
  61.282 +                                        }
  61.283 +                                }
  61.284 +                                if (discint==2 || discint==5 || discint==6 || discint==10)
  61.285 +                                {
  61.286 +//                                        pclog("Rate %i %i %i\n",fdc.rate,discrate[fdc.drive],driveempty[fdc.drive]);
  61.287 +                                        if (fdc.rate!=discrate[fdc.drive])
  61.288 +                                        {
  61.289 +//                                                pclog("Wrong rate %i %i\n",fdc.rate,discrate[fdc.drive]);
  61.290 +                                                discint=0xFF;
  61.291 +                                                disctime=1024;
  61.292 +                                        }
  61.293 +                                        if (driveempty[fdc.drive])
  61.294 +                                        {
  61.295 +//                                                pclog("Drive empty\n");
  61.296 +                                                discint=0xFE;
  61.297 +                                                disctime=1024;
  61.298 +                                        }
  61.299 +                                }
  61.300 +                                if (discint == 7 || discint == 0xf)
  61.301 +                                {
  61.302 +                                        fdc.stat =  1 << fdc.drive;
  61.303 +//                                        disctime = 8000000;
  61.304 +                                }
  61.305 +                                if (discint == 0xf)
  61.306 +                                {
  61.307 +                                        fdc.head = (fdc.params[0] & 4) ? 1 : 0;
  61.308 +                                }
  61.309 +//                                if (discint==5) fdc.pos=512;
  61.310 +                        }
  61.311 +                }
  61.312 +                return;
  61.313 +                case 7:
  61.314 +                        if (!AT) return;
  61.315 +                fdc.rate=val&3;
  61.316 +
  61.317 +                disc_3f7=val;
  61.318 +                return;
  61.319 +        }
  61.320 +//        printf("Write FDC %04X %02X\n",addr,val);
  61.321 +//        dumpregs();
  61.322 +//        exit(-1);
  61.323 +}
  61.324 +
  61.325 +int paramstogo=0;
  61.326 +uint8_t fdc_read(uint16_t addr)
  61.327 +{
  61.328 +        uint8_t temp;
  61.329 +//        /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,ins);
  61.330 +        switch (addr&7)
  61.331 +        {
  61.332 +                case 1: /*???*/
  61.333 +                temp=0x50;
  61.334 +                break;
  61.335 +                case 3:
  61.336 +                temp = 0x20;
  61.337 +                break;
  61.338 +                case 4: /*Status*/
  61.339 +                temp=fdc.stat;
  61.340 +                break;
  61.341 +                case 5: /*Data*/
  61.342 +                fdc.stat&=~0x80;
  61.343 +                if (paramstogo)
  61.344 +                {
  61.345 +                        paramstogo--;
  61.346 +                        temp=fdc.res[10 - paramstogo];
  61.347 +//                        printf("Read param %i %02X\n",6-paramstogo,temp);
  61.348 +                        if (!paramstogo)
  61.349 +                        {
  61.350 +                                fdc.stat=0x80;
  61.351 +//                                fdc.st0=0;
  61.352 +                        }
  61.353 +                        else
  61.354 +                        {
  61.355 +                                fdc.stat|=0xC0;
  61.356 +//                                fdc_poll();
  61.357 +                        }
  61.358 +                }
  61.359 +                else
  61.360 +                {
  61.361 +                        if (lastbyte)
  61.362 +                           fdc.stat=0x80;
  61.363 +                        lastbyte=0;
  61.364 +                        temp=fdc.dat;
  61.365 +                }
  61.366 +                if (discint==0xA) disctime=1024;
  61.367 +                fdc.stat &= 0xf0;
  61.368 +                break;
  61.369 +                case 7: /*Disk change*/
  61.370 +                if (fdc.dor & (0x10 << (fdc.dor & 1)))
  61.371 +                   temp = (discchanged[fdc.dor & 1] || driveempty[fdc.dor & 1])?0x80:0;
  61.372 +                else
  61.373 +                   temp = 0;
  61.374 +                if (AMSTRADIO)  /*PC2086/3086 seem to reverse this bit*/
  61.375 +                   temp ^= 0x80;
  61.376 +//                printf("- DC %i %02X %02X %i %i - ",fdc.dor & 1, fdc.dor, 0x10 << (fdc.dor & 1), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]);
  61.377 +//                discchanged[fdc.dor&1]=0;
  61.378 +                break;
  61.379 +                default:
  61.380 +                        temp=0xFF;
  61.381 +//                printf("Bad read FDC %04X\n",addr);
  61.382 +//                dumpregs();
  61.383 +//                exit(-1);
  61.384 +        }
  61.385 +//        /*if (addr!=0x3f4) */printf("%02X rate=%i\n",temp,fdc.rate);
  61.386 +        return temp;
  61.387 +}
  61.388 +
  61.389 +int fdc_abort_f = 0;
  61.390 +
  61.391 +void fdc_abort()
  61.392 +{
  61.393 +        fdc_abort_f = 1;
  61.394 +//        pclog("FDC ABORT\n");
  61.395 +}
  61.396 +
  61.397 +static int fdc_reset_stat = 0;
  61.398 +void fdc_poll()
  61.399 +{
  61.400 +        int temp;
  61.401 +//        pclog("fdc_poll %08X %i %02X\n", discint, fdc.drive, fdc.st0);
  61.402 +        switch (discint)
  61.403 +        {
  61.404 +                case -3: /*End of command with interrupt*/
  61.405 +//                if (output) printf("EOC - interrupt!\n");
  61.406 +//pclog("EOC\n");
  61.407 +                picint(0x40);
  61.408 +                case -2: /*End of command*/
  61.409 +                fdc.stat = (fdc.stat & 0xf) | 0x80;
  61.410 +                return;
  61.411 +                case -1: /*Reset*/
  61.412 +//pclog("Reset\n");
  61.413 +                picint(0x40);
  61.414 +                fdc_reset_stat = 4;
  61.415 +                return;
  61.416 +                case 2: /*Read track*/
  61.417 +                if (!fdc.pos)
  61.418 +                {
  61.419 +//                        printf("Read Track Side %i Track %i Sector %02X sector size %i end sector %02X %05X\n",fdc.head,fdc.track,fdc.sector,fdc.params[4],fdc.params[5],(dma.page[2]<<16)+dma.ac[2]);
  61.420 +                }
  61.421 +                if (fdc.pos<512)
  61.422 +                {
  61.423 +                        fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
  61.424 +//                        pclog("Read %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
  61.425 +                        writedma2(fdc.dat);
  61.426 +                        disctime=60;
  61.427 +                }
  61.428 +                else
  61.429 +                {
  61.430 +                        disctime=0;
  61.431 +                        discint=-2;
  61.432 +//                        pclog("RT\n");
  61.433 +                        picint(0x40);
  61.434 +                        fdc.stat=0xD0;
  61.435 +                        fdc.res[4]=(fdc.head?4:0)|fdc.drive;
  61.436 +                        fdc.res[5]=fdc.res[2]=0;
  61.437 +                        fdc.res[6]=fdc.track[fdc.drive];
  61.438 +                        fdc.res[7]=fdc.head;
  61.439 +                        fdc.res[8]=fdc.sector;
  61.440 +                        fdc.res[9]=fdc.params[4];
  61.441 +                        paramstogo=7;
  61.442 +                        return;
  61.443 +                        disctime=1024;
  61.444 +                        picint(0x40);
  61.445 +                        fdc.stat=0xD0;
  61.446 +                        switch (fdc.pos-512)
  61.447 +                        {
  61.448 +                                case 0: case 1: case 2: fdc.dat=0; break;
  61.449 +                                case 3: fdc.dat=fdc.track[fdc.drive]; break;
  61.450 +                                case 4: fdc.dat=fdc.head; break;
  61.451 +                                case 5: fdc.dat=fdc.sector; break;
  61.452 +                                case 6: fdc.dat=fdc.params[4]; discint=-2; lastbyte=1; break;
  61.453 +                        }
  61.454 +                }
  61.455 +                fdc.pos++;
  61.456 +                if (fdc.pos==512 && fdc.params[5]!=1)
  61.457 +                {
  61.458 +                        fdc.pos=0;
  61.459 +                        fdc.sector++;
  61.460 +                        if (fdc.sector==SECTORS[fdc.drive]+1)
  61.461 +                        {
  61.462 +                                fdc.sector=1;
  61.463 +                        }
  61.464 +                        fdc.params[5]--;
  61.465 +                }
  61.466 +                return;
  61.467 +                case 3: /*Specify*/
  61.468 +                fdc.stat=0x80;
  61.469 +                fdc.specify[0] = fdc.params[0];
  61.470 +                fdc.specify[1] = fdc.params[1];
  61.471 +                return;
  61.472 +                case 4: /*Sense drive status*/
  61.473 +                fdc.res[10] = (fdc.params[0] & 7) | 0x28;
  61.474 +                if (!fdc.track[fdc.drive]) fdc.res[10] |= 0x10;
  61.475 +
  61.476 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.477 +                paramstogo = 1;
  61.478 +                discint = 0;
  61.479 +                disctime = 0;
  61.480 +                return;
  61.481 +                case 5: /*Write data*/
  61.482 +                discmodified[fdc.drive]=1;
  61.483 +//                printf("Write data %i\n",fdc.pos);
  61.484 +                if (!fdc.pos)
  61.485 +                {
  61.486 +//                        printf("Write data Side %i Track %i Sector %02X sector size %i end sector %02X\n",fdc.params[2],fdc.params[1],fdc.params[3],fdc.params[4],fdc.params[5]);
  61.487 +//                        dumpregs();
  61.488 +//                        exit(-1);
  61.489 +                }
  61.490 +                if (fdc.pos<512)
  61.491 +                {
  61.492 +                        temp=readdma2();
  61.493 +                        if (fdc_abort_f)
  61.494 +                        {
  61.495 +                                fdc_abort_f=0;
  61.496 +                                discint=0xFD;
  61.497 +                                disctime=50;
  61.498 +                                return;
  61.499 +                        }
  61.500 +                        else
  61.501 +                        {
  61.502 +                                fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos]=temp;
  61.503 +//                                printf("Write data %i %i %02X   %i:%i:%i:%i\n",fdc.sector-1,fdc.pos,fdc.dat,fdc.head,fdc.track[fdc.drive],fdc.sector-1,fdc.pos);
  61.504 +                                disctime=60;
  61.505 +                        }
  61.506 +                }
  61.507 +                else
  61.508 +                {
  61.509 +                        disctime=0;
  61.510 +                        discint=-2;
  61.511 +//                        pclog("WD\n");
  61.512 +                        picint(0x40);
  61.513 +                        fdc.stat=0xD0;
  61.514 +                        fdc.res[4]=(fdc.head?4:0)|fdc.drive;
  61.515 +                        fdc.res[5]=0;
  61.516 +                        fdc.res[6]=0;
  61.517 +                        fdc.res[7]=fdc.track[fdc.drive];
  61.518 +                        fdc.res[8]=fdc.head;
  61.519 +                        fdc.res[9]=fdc.sector;
  61.520 +                        fdc.res[10]=fdc.params[4];
  61.521 +                        paramstogo=7;
  61.522 +                        return;
  61.523 +                        disctime=1024;
  61.524 +                        picint(0x40);
  61.525 +                        fdc.stat=0xD0;
  61.526 +                        switch (fdc.pos-512)
  61.527 +                        {
  61.528 +                                case 0: fdc.dat=0x40; break;
  61.529 +                                case 1: fdc.dat=2; break;
  61.530 +                                case 2: fdc.dat=0; break;
  61.531 +                                case 3: fdc.dat=fdc.track[fdc.drive]; break;
  61.532 +                                case 4: fdc.dat=fdc.head; break;
  61.533 +                                case 5: fdc.dat=fdc.sector; break;
  61.534 +                                case 6: fdc.dat=fdc.params[4]; discint=-2; break;
  61.535 +                        }
  61.536 +                }
  61.537 +                fdc.pos++;
  61.538 +                if (fdc.pos==512 && fdc.sector!=fdc.params[5])
  61.539 +                {
  61.540 +                        fdc.pos=0;
  61.541 +                        fdc.sector++;
  61.542 +                }
  61.543 +                return;
  61.544 +                case 6: /*Read data*/
  61.545 +                if (!fdc.pos)
  61.546 +                {
  61.547 +//                        printf("Reading sector %i track %i side %i drive %i %02X to %05X\n",fdc.sector,fdc.track[fdc.drive],fdc.head,fdc.drive,fdc.params[5],(dma.ac[2]+(dma.page[2]<<16))&rammask);
  61.548 +                }
  61.549 +                if (fdc.pos<512)
  61.550 +                {
  61.551 +                        fdc.dat=disc[fdc.drive][fdc.head][fdc.track[fdc.drive]][fdc.sector-1][fdc.pos];
  61.552 +//                        printf("Read disc %i %i %i %i %02X\n",fdc.head,fdc.track,fdc.sector,fdc.pos,fdc.dat);
  61.553 +                        writedma2(fdc.dat);
  61.554 +                        disctime=60;
  61.555 +                }
  61.556 +                else
  61.557 +                {
  61.558 +//                        printf("End of command - params to go!\n");
  61.559 +                        fdc_abort_f = 0;
  61.560 +                        disctime=0;
  61.561 +                        discint=-2;
  61.562 +                        picint(0x40);
  61.563 +//                        pclog("RD\n");
  61.564 +                        fdc.stat=0xD0;
  61.565 +                        fdc.res[4]=(fdc.head?4:0)|fdc.drive;
  61.566 +                        fdc.res[5]=fdc.res[6]=0;
  61.567 +                        fdc.res[7]=fdc.track[fdc.drive];
  61.568 +                        fdc.res[8]=fdc.head;
  61.569 +                        fdc.res[9]=fdc.sector;
  61.570 +                        fdc.res[10]=fdc.params[4];
  61.571 +                        paramstogo=7;
  61.572 +                        return;
  61.573 +                        switch (fdc.pos-512)
  61.574 +                        {
  61.575 +                                case 0: case 1: case 2: fdc.dat=0; break;
  61.576 +                                case 3: fdc.dat=fdc.track[fdc.drive]; break;
  61.577 +                                case 4: fdc.dat=fdc.head; break;
  61.578 +                                case 5: fdc.dat=fdc.sector; break;
  61.579 +                                case 6: fdc.dat=fdc.params[4]; discint=-2; lastbyte=1; break;
  61.580 +                        }
  61.581 +                }
  61.582 +                fdc.pos++;
  61.583 +                if (fdc.pos==512)// && fdc.sector!=fdc.params[5])
  61.584 +                {
  61.585 +//                        printf("Sector complete! %02X\n",fdc.params[5]);
  61.586 +                        fdc.pos=0;
  61.587 +                        fdc.sector++;
  61.588 +                        if (fdc.sector > fdc.params[5])
  61.589 +                        {
  61.590 +//                                printf("Overrunnit!\n");
  61.591 +//                                dumpregs();
  61.592 +//                                exit(-1);
  61.593 +                                fdc.sector=1;
  61.594 +                                if (fdc.command & 0x80)
  61.595 +                                {
  61.596 +                                        fdc.head ^= 1;
  61.597 +                                        if (!fdc.head)
  61.598 +                                        {
  61.599 +                                                fdc.track[fdc.drive]++;
  61.600 +                                                if (fdc.track[fdc.drive] >= TRACKS[fdc.drive])
  61.601 +                                                {
  61.602 +                                                        fdc.track[fdc.drive] = TRACKS[fdc.drive];
  61.603 +                                                        fdc.pos = 512;
  61.604 +                                                }
  61.605 +                                        }
  61.606 +                                }
  61.607 +                                else
  61.608 +                                   fdc.pos = 512;
  61.609 +                        }
  61.610 +                        if (fdc_abort_f)
  61.611 +                           fdc.pos = 512;
  61.612 +                }
  61.613 +                return;
  61.614 +/*                printf("Read data\n");
  61.615 +                printf("Side %i Track %i Sector %i sector size %i\n",fdc.params[1],fdc.params[2],fdc.params[3],fdc.params[4]);
  61.616 +                dumpregs();
  61.617 +                exit(-1);*/
  61.618 +                case 7: /*Recalibrate*/
  61.619 +                fdc.track[fdc.drive]=0;
  61.620 +                if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
  61.621 +                fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
  61.622 +                discint=-3;
  61.623 +                disctime=2048;
  61.624 +//                printf("Recalibrate complete!\n");
  61.625 +                fdc.stat = 0x80 | (1 << fdc.drive);
  61.626 +                return;
  61.627 +                case 8: /*Sense interrupt status*/
  61.628 +//                pclog("Sense interrupt status %i\n", fdc_reset_stat);
  61.629 +                
  61.630 +                fdc.dat = fdc.st0;
  61.631 +
  61.632 +                if (fdc_reset_stat)
  61.633 +                {
  61.634 +                        fdc.st0 = (fdc.st0 & 0xf8) | (4 - fdc_reset_stat) | (fdc.head ? 4 : 0);
  61.635 +                        fdc_reset_stat--;
  61.636 +                }
  61.637 +                fdc.stat    = (fdc.stat & 0xf) | 0xd0;
  61.638 +                fdc.res[9]  = fdc.st0;
  61.639 +                fdc.res[10] = fdc.track[fdc.drive];
  61.640 +                if (!fdc_reset_stat) fdc.st0 = 0x80;
  61.641 +
  61.642 +                paramstogo = 2;
  61.643 +                discint = 0;
  61.644 +                disctime = 0;
  61.645 +                return;
  61.646 +                case 10: /*Read sector ID*/
  61.647 +                disctime=0;
  61.648 +                discint=-2;
  61.649 +                picint(0x40);
  61.650 +                fdc.stat=0xD0;
  61.651 +                fdc.res[4]=(fdc.head?4:0)|fdc.drive;
  61.652 +                fdc.res[5]=0;
  61.653 +                fdc.res[6]=0;
  61.654 +                fdc.res[7]=fdc.track[fdc.drive];
  61.655 +                fdc.res[8]=fdc.head;
  61.656 +                fdc.res[9]=fdc.sector;
  61.657 +                fdc.res[10]=fdc.params[4];
  61.658 +                paramstogo=7;
  61.659 +                fdc.sector++;
  61.660 +                if (fdc.sector==SECTORS[fdc.drive]+1)
  61.661 +                   fdc.sector=1;
  61.662 +                return;
  61.663 +                case 15: /*Seek*/
  61.664 +                fdc.track[fdc.drive]=fdc.params[1];
  61.665 +                if (!driveempty[fdc.dor & 1]) discchanged[fdc.dor & 1] = 0;
  61.666 +//                printf("Seeked to track %i %i\n",fdc.track[fdc.drive], fdc.drive);
  61.667 +                fdc.st0=0x20|fdc.drive|(fdc.head?4:0);
  61.668 +                discint=-3;
  61.669 +                disctime=2048;
  61.670 +                fdc.stat = 0x80 | (1 << fdc.drive);
  61.671 +//                pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0);
  61.672 +                return;
  61.673 +                case 0x0e: /*Dump registers*/
  61.674 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.675 +                fdc.res[3] = fdc.track[0];
  61.676 +                fdc.res[4] = fdc.track[1];
  61.677 +                fdc.res[5] = 0;
  61.678 +                fdc.res[6] = 0;
  61.679 +                fdc.res[7] = fdc.specify[0];
  61.680 +                fdc.res[8] = fdc.specify[1];
  61.681 +                fdc.res[9] = fdc.eot[fdc.drive];
  61.682 +                fdc.res[10] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0);
  61.683 +                paramstogo=10;
  61.684 +                discint=0;
  61.685 +                disctime=0;
  61.686 +                return;
  61.687 +
  61.688 +                case 0x10: /*Version*/
  61.689 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.690 +                fdc.res[10] = 0x90;
  61.691 +                paramstogo=1;
  61.692 +                discint=0;
  61.693 +                disctime=0;
  61.694 +                return;
  61.695 +                
  61.696 +                case 0x12:
  61.697 +                fdc.perp = fdc.params[0];
  61.698 +                fdc.stat = 0x80;
  61.699 +                disctime = 0;
  61.700 +//                picint(0x40);
  61.701 +                return;
  61.702 +                case 0x13: /*Configure*/
  61.703 +                fdc.config = fdc.params[1];
  61.704 +                fdc.pretrk = fdc.params[2];
  61.705 +                fdc.stat = 0x80;
  61.706 +                disctime = 0;
  61.707 +//                picint(0x40);
  61.708 +                return;
  61.709 +                case 0x14: /*Unlock*/
  61.710 +                fdc.lock = 0;
  61.711 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.712 +                fdc.res[10] = 0;
  61.713 +                paramstogo=1;
  61.714 +                discint=0;
  61.715 +                disctime=0;
  61.716 +                return;
  61.717 +                case 0x94: /*Lock*/
  61.718 +                fdc.lock = 1;
  61.719 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.720 +                fdc.res[10] = 0x10;
  61.721 +                paramstogo=1;
  61.722 +                discint=0;
  61.723 +                disctime=0;
  61.724 +                return;
  61.725 +
  61.726 +
  61.727 +                case 0xfc: /*Invalid*/
  61.728 +                fdc.dat = fdc.st0 = 0x80;
  61.729 +//                pclog("Inv!\n");
  61.730 +                //picint(0x40);
  61.731 +                fdc.stat = (fdc.stat & 0xf) | 0xd0;
  61.732 +//                fdc.stat|=0xC0;
  61.733 +                fdc.res[10] = fdc.st0;
  61.734 +                paramstogo=1;
  61.735 +                discint=0;
  61.736 +                disctime=0;
  61.737 +                return;
  61.738 +
  61.739 +                case 0xFD: /*DMA aborted (PC1512)*/
  61.740 +                /*In the absence of other information, lie and claim the command completed successfully.
  61.741 +                  The PC1512 BIOS likes to program the FDC to write to all sectors on the track, but
  61.742 +                  program the DMA length to the number of sectors actually transferred. Not aborting
  61.743 +                  correctly causes disc corruption.
  61.744 +                  This only matters on writes, on reads the DMA controller will ignore excess data.
  61.745 +                  */
  61.746 +                pclog("DMA Aborted\n");
  61.747 +                disctime=0;
  61.748 +                discint=-2;
  61.749 +                picint(0x40);
  61.750 +                fdc.stat=0xD0;
  61.751 +                fdc.res[4]=(fdc.head?4:0)|fdc.drive;
  61.752 +                fdc.res[5]=0;
  61.753 +                fdc.res[6]=0;
  61.754 +                fdc.res[7]=fdc.track[fdc.drive];
  61.755 +                fdc.res[8]=fdc.head;
  61.756 +                fdc.res[9]=fdc.sector;
  61.757 +                fdc.res[10]=fdc.params[4];
  61.758 +                paramstogo=7;
  61.759 +                return;
  61.760 +                case 0xFE: /*Drive empty*/
  61.761 +                pclog("Drive empty\n");
  61.762 +                fdc.stat = 0x10;
  61.763 +                disctime = 0;
  61.764 +/*                disctime=0;
  61.765 +                discint=-2;
  61.766 +                picint(0x40);
  61.767 +                fdc.stat=0xD0;
  61.768 +                fdc.res[4]=0xC8|(fdc.head?4:0)|fdc.drive;
  61.769 +                fdc.res[5]=0;
  61.770 +                fdc.res[6]=0;
  61.771 +                fdc.res[7]=0;
  61.772 +                fdc.res[8]=0;
  61.773 +                fdc.res[9]=0;
  61.774 +                fdc.res[10]=0;
  61.775 +                paramstogo=7;*/
  61.776 +                return;
  61.777 +                case 0xFF: /*Wrong rate*/
  61.778 +                pclog("Wrong rate\n");
  61.779 +                disctime=0;
  61.780 +                discint=-2;
  61.781 +                picint(0x40);
  61.782 +                fdc.stat=0xD0;
  61.783 +                fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
  61.784 +                fdc.res[5]=5;
  61.785 +                fdc.res[6]=0;
  61.786 +                fdc.res[7]=0;
  61.787 +                fdc.res[8]=0;
  61.788 +                fdc.res[9]=0;
  61.789 +                fdc.res[10]=0;
  61.790 +                paramstogo=7;
  61.791 +                return;
  61.792 +        }
  61.793 +//        printf("Bad FDC disc int %i\n",discint);
  61.794 +//        dumpregs();
  61.795 +//        exit(-1);
  61.796 +}
  61.797 +
  61.798 +
  61.799 +void fdc_init()
  61.800 +{
  61.801 +        io_sethandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL);
  61.802 +        io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL);        
  61.803 +}
  61.804 +
  61.805 +void fdc_remove()
  61.806 +{
  61.807 +        io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL);
  61.808 +        io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL);        
  61.809 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/src/fdc.h	Sun Apr 21 14:54:35 2013 +0100
    62.3 @@ -0,0 +1,4 @@
    62.4 +void fdc_init();
    62.5 +void fdc_remove();
    62.6 +void fdc_reset();
    62.7 +void fdc_poll();
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/src/filters.h	Sun Apr 21 14:54:35 2013 +0100
    63.3 @@ -0,0 +1,178 @@
    63.4 +#define NCoef 2
    63.5 +
    63.6 +//fc=350Hz
    63.7 +static inline float low_iir(int i, float NewSample) {
    63.8 +    float ACoef[NCoef+1] = {
    63.9 +        0.00049713569693400649,
   63.10 +        0.00099427139386801299,
   63.11 +        0.00049713569693400649
   63.12 +    };
   63.13 +
   63.14 +    float BCoef[NCoef+1] = {
   63.15 +        1.00000000000000000000,
   63.16 +        -1.93522955470669530000,
   63.17 +        0.93726236021404663000
   63.18 +    };
   63.19 +
   63.20 +    static float y[2][NCoef+1]; //output samples
   63.21 +    static float x[2][NCoef+1]; //input samples
   63.22 +    int n;
   63.23 +
   63.24 +    //shift the old samples
   63.25 +    for(n=NCoef; n>0; n--) {
   63.26 +       x[i][n] = x[i][n-1];
   63.27 +       y[i][n] = y[i][n-1];
   63.28 +    }
   63.29 +
   63.30 +    //Calculate the new output
   63.31 +    x[i][0] = NewSample;
   63.32 +    y[i][0] = ACoef[0] * x[i][0];
   63.33 +    for(n=1; n<=NCoef; n++)
   63.34 +        y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
   63.35 +
   63.36 +    return y[i][0];
   63.37 +}
   63.38 +
   63.39 +//fc=350Hz
   63.40 +static inline float low_cut_iir(int i, float NewSample) {
   63.41 +    float ACoef[NCoef+1] = {
   63.42 +        0.96839970114733542000,
   63.43 +        -1.93679940229467080000,
   63.44 +        0.96839970114733542000
   63.45 +    };
   63.46 +
   63.47 +    float BCoef[NCoef+1] = {
   63.48 +        1.00000000000000000000,
   63.49 +        -1.93522955471202770000,
   63.50 +        0.93726236021916731000
   63.51 +    };
   63.52 +
   63.53 +    static float y[2][NCoef+1]; //output samples
   63.54 +    static float x[2][NCoef+1]; //input samples
   63.55 +    int n;
   63.56 +
   63.57 +    //shift the old samples
   63.58 +    for(n=NCoef; n>0; n--) {
   63.59 +       x[i][n] = x[i][n-1];
   63.60 +       y[i][n] = y[i][n-1];
   63.61 +    }
   63.62 +
   63.63 +    //Calculate the new output
   63.64 +    x[i][0] = NewSample;
   63.65 +    y[i][0] = ACoef[0] * x[i][0];
   63.66 +    for(n=1; n<=NCoef; n++)
   63.67 +        y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
   63.68 +
   63.69 +    return y[i][0];
   63.70 +}
   63.71 +
   63.72 +//fc=3.5kHz
   63.73 +static inline float high_iir(int i, float NewSample) {
   63.74 +    float ACoef[NCoef+1] = {
   63.75 +        0.72248704753064896000,
   63.76 +        -1.44497409506129790000,
   63.77 +        0.72248704753064896000
   63.78 +    };
   63.79 +
   63.80 +    float BCoef[NCoef+1] = {
   63.81 +        1.00000000000000000000,
   63.82 +        -1.36640781670578510000,
   63.83 +        0.52352474706139873000
   63.84 +    };
   63.85 +    static float y[2][NCoef+1]; //output samples
   63.86 +    static float x[2][NCoef+1]; //input samples
   63.87 +    int n;
   63.88 +
   63.89 +    //shift the old samples
   63.90 +    for(n=NCoef; n>0; n--) {
   63.91 +       x[i][n] = x[i][n-1];
   63.92 +       y[i][n] = y[i][n-1];
   63.93 +    }
   63.94 +
   63.95 +    //Calculate the new output
   63.96 +    x[i][0] = NewSample;
   63.97 +    y[i][0] = ACoef[0] * x[i][0];
   63.98 +    for(n=1; n<=NCoef; n++)
   63.99 +        y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
  63.100 +
  63.101 +    return y[i][0];
  63.102 +}
  63.103 +
  63.104 +//fc=3.5kHz
  63.105 +static inline float high_cut_iir(int i, float NewSample) {
  63.106 +    float ACoef[NCoef+1] = {
  63.107 +        0.03927726802250377400,
  63.108 +        0.07855453604500754700,
  63.109 +        0.03927726802250377400
  63.110 +    };
  63.111 +
  63.112 +    float BCoef[NCoef+1] = {
  63.113 +        1.00000000000000000000,
  63.114 +        -1.36640781666419950000,
  63.115 +        0.52352474703279628000
  63.116 +    };
  63.117 +    static float y[2][NCoef+1]; //output samples
  63.118 +    static float x[2][NCoef+1]; //input samples
  63.119 +    int n;
  63.120 +
  63.121 +    //shift the old samples
  63.122 +    for(n=NCoef; n>0; n--) {
  63.123 +       x[i][n] = x[i][n-1];
  63.124 +       y[i][n] = y[i][n-1];
  63.125 +    }
  63.126 +
  63.127 +    //Calculate the new output
  63.128 +    x[i][0] = NewSample;
  63.129 +    y[i][0] = ACoef[0] * x[i][0];
  63.130 +    for(n=1; n<=NCoef; n++)
  63.131 +        y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
  63.132 +
  63.133 +    return y[i][0];
  63.134 +}
  63.135 +
  63.136 +
  63.137 +#undef NCoef
  63.138 +#define NCoef 1
  63.139 +
  63.140 +//fc=3.2kHz
  63.141 +static inline float sb_iir(int i, float NewSample) {
  63.142 +/*    float ACoef[NCoef+1] = {
  63.143 +        0.03356837051492005100,
  63.144 +        0.06713674102984010200,
  63.145 +        0.03356837051492005100
  63.146 +    };
  63.147 +
  63.148 +    float BCoef[NCoef+1] = {
  63.149 +        1.00000000000000000000,
  63.150 +        -1.41898265221812010000,
  63.151 +        0.55326988968868285000
  63.152 +    };*/
  63.153 +    
  63.154 +    float ACoef[NCoef+1] = {
  63.155 +        0.17529642630084405000,
  63.156 +        0.17529642630084405000
  63.157 +    };
  63.158 +
  63.159 +    float BCoef[NCoef+1] = {
  63.160 +        1.00000000000000000000,
  63.161 +        -0.64940759319751051000
  63.162 +    };
  63.163 +    static float y[2][NCoef+1]; //output samples
  63.164 +    static float x[2][NCoef+1]; //input samples
  63.165 +    int n;
  63.166 +
  63.167 +    //shift the old samples
  63.168 +    for(n=NCoef; n>0; n--) {
  63.169 +       x[i][n] = x[i][n-1];
  63.170 +       y[i][n] = y[i][n-1];
  63.171 +    }
  63.172 +
  63.173 +    //Calculate the new output
  63.174 +    x[i][0] = NewSample;
  63.175 +    y[i][0] = ACoef[0] * x[i][0];
  63.176 +    for(n=1; n<=NCoef; n++)
  63.177 +        y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
  63.178 +
  63.179 +    return y[i][0];
  63.180 +}
  63.181 +
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/src/gus.c	Sun Apr 21 14:54:35 2013 +0100
    64.3 @@ -0,0 +1,625 @@
    64.4 +#include <stdio.h>
    64.5 +#include <stdlib.h>
    64.6 +#include <string.h>
    64.7 +#include "ibm.h"
    64.8 +
    64.9 +extern int ins;
   64.10 +extern int timetolive;
   64.11 +int output;
   64.12 +//#define GUSRATECONST (44100.0/48000.0)
   64.13 +uint8_t *gusram;
   64.14 +
   64.15 +struct
   64.16 +{
   64.17 +        int global;
   64.18 +        uint32_t addr,dmaaddr;
   64.19 +        int voice;
   64.20 +        uint32_t start[32],end[32],cur[32];
   64.21 +        uint32_t startx[32],endx[32],curx[32];
   64.22 +        uint32_t rstart[32],rend[32],rcur[32];
   64.23 +        uint16_t freq[32];
   64.24 +        uint16_t rfreq[32];
   64.25 +        uint8_t ctrl[32];
   64.26 +        uint8_t rctrl[32];
   64.27 +        int curvol[32];
   64.28 +        int t1on,t2on;
   64.29 +        uint8_t tctrl;
   64.30 +        uint16_t t1,t2,t1l,t2l;
   64.31 +        uint8_t irqstatus,irqstatus2;
   64.32 +        uint8_t adcommand;
   64.33 +        int waveirqs[32],rampirqs[32];
   64.34 +        int voices;
   64.35 +        uint8_t dmactrl;
   64.36 +} gus;
   64.37 +
   64.38 +double vol16bit[4096];
   64.39 +
   64.40 +void initgus()
   64.41 +{
   64.42 +        int c;
   64.43 +        for (c=0;c<32;c++)
   64.44 +        {
   64.45 +                gus.ctrl[c]=1;
   64.46 +                gus.rctrl[c]=1;
   64.47 +                gus.rfreq[c]=63*512;
   64.48 +        }
   64.49 +        gusram=malloc(1024*1024);
   64.50 +
   64.51 +	double out = 1.0;
   64.52 +	for (c=4095;c>=0;c--) {
   64.53 +		vol16bit[c]=out;//(float)c/4095.0;//out;
   64.54 +		out/=1.002709201;		/* 0.0235 dB Steps */
   64.55 +	}
   64.56 +
   64.57 +	printf("Top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]);
   64.58 +	gus.voices=14;
   64.59 +
   64.60 +}
   64.61 +
   64.62 +void dumpgus()
   64.63 +{
   64.64 +/*        FILE *f=fopen("gusram.dmp","wb");
   64.65 +        fwrite(gusram,1024*1024,1,f);
   64.66 +        fclose(f);*/
   64.67 +}
   64.68 +
   64.69 +void pollgusirqs()
   64.70 +{
   64.71 +        int c;
   64.72 +        gus.irqstatus&=~0x60;
   64.73 +        for (c=0;c<32;c++)
   64.74 +        {
   64.75 +                if (gus.waveirqs[c])
   64.76 +                {
   64.77 +//                        gus.waveirqs[c]=0;
   64.78 +                        gus.irqstatus2=0x60|c;
   64.79 +                        gus.irqstatus|=0x20;
   64.80 +//                        printf("Voice IRQ %i %02X %i\n",c,gus.irqstatus2,ins);
   64.81 +                        picintlevel(0x20);
   64.82 +//                        output=3;
   64.83 +//                        timetolive=5000;
   64.84 +                        return;
   64.85 +                }
   64.86 +                if (gus.rampirqs[c])
   64.87 +                {
   64.88 +//                        gus.rampirqs[c]=0;
   64.89 +                        gus.irqstatus2=0xA0|c;
   64.90 +                        gus.irqstatus|=0x40;
   64.91 +//                        printf("Ramp IRQ %i %02X %i\n",c,gus.irqstatus2,ins);
   64.92 +                        picintlevel(0x20);
   64.93 +                        return;
   64.94 +                }
   64.95 +        }
   64.96 +        gus.irqstatus2=0xE0;
   64.97 +//        gus.irqstatus&=~0x20;
   64.98 +        if (!gus.irqstatus) picintc(0x20);
   64.99 +}
  64.100 +
  64.101 +int gusirqnext=0;
  64.102 +
  64.103 +void writegus(uint16_t addr, uint8_t val)
  64.104 +{
  64.105 +        int c,d;
  64.106 +//        printf("Write GUS %04X %02X %04X:%04X\n",addr,val,CS,pc);
  64.107 +        switch (addr)
  64.108 +        {
  64.109 +                case 0x342: /*Voice select*/
  64.110 +                gus.voice=val&31;
  64.111 +                break;
  64.112 +                case 0x343: /*Global select*/
  64.113 +                gus.global=val;
  64.114 +                break;
  64.115 +                case 0x344: /*Global low*/
  64.116 +//                if (gus.global!=0x43 && gus.global!=0x44) printf("Writing register %02X %02X %02X\n",gus.global,gus.voice,val);
  64.117 +                switch (gus.global)
  64.118 +                {
  64.119 +                        case 0: /*Voice control*/
  64.120 +//                        if (val&1 && !(gus.ctrl[gus.voice]&1)) printf("Voice on %i\n",gus.voice);
  64.121 +                        gus.ctrl[gus.voice]=val;
  64.122 +                        break;
  64.123 +                        case 1: /*Frequency control*/
  64.124 +                        gus.freq[gus.voice]=(gus.freq[gus.voice]&0xFF00)|val;
  64.125 +                        break;
  64.126 +                        case 2: /*Start addr high*/
  64.127 +                        gus.startx[gus.voice]=(gus.startx[gus.voice]&0xF807F)|(val<<7);
  64.128 +                        gus.start[gus.voice]=(gus.start[gus.voice]&0x1F00FFFF)|(val<<16);
  64.129 +//                        printf("Write %i start %08X %08X\n",gus.voice,gus.start[gus.voice],gus.startx[gus.voice]);
  64.130 +                        break;
  64.131 +                        case 3: /*Start addr low*/
  64.132 +                        gus.start[gus.voice]=(gus.start[gus.voice]&0x1FFFFF00)|val;
  64.133 +//                        printf("Write %i start %08X %08X\n",gus.voice,gus.start[gus.voice],gus.startx[gus.voice]);
  64.134 +                        break;
  64.135 +                        case 4: /*End addr high*/
  64.136 +                        gus.endx[gus.voice]=(gus.endx[gus.voice]&0xF807F)|(val<<7);
  64.137 +                        gus.end[gus.voice]=(gus.end[gus.voice]&0x1F00FFFF)|(val<<16);
  64.138 +//                        printf("Write %i end %08X %08X\n",gus.voice,gus.end[gus.voice],gus.endx[gus.voice]);
  64.139 +                        break;
  64.140 +                        case 5: /*End addr low*/
  64.141 +                        gus.end[gus.voice]=(gus.end[gus.voice]&0x1FFFFF00)|val;
  64.142 +//                        printf("Write %i end %08X %08X\n",gus.voice,gus.end[gus.voice],gus.endx[gus.voice]);
  64.143 +                        break;
  64.144 +
  64.145 +                        case 0x6: /*Ramp frequency*/
  64.146 +                        gus.rfreq[gus.voice] = (int)( (double)((val & 63)*512)/(double)(1 << (3*(val >> 6))));
  64.147 +//                        printf("RFREQ %02X %i %i %f\n",val,gus.voice,gus.rfreq[gus.voice],(double)(val & 63)/(double)(1 << (3*(val >> 6))));
  64.148 +                        break;
  64.149 +
  64.150 +                        case 0x9: /*Current volume*/
  64.151 +                        gus.curvol[gus.voice]=gus.rcur[gus.voice]=(gus.rcur[gus.voice]&0x1FE0000)|(val<<9);
  64.152 +//                        printf("Vol %i is %04X\n",gus.voice,gus.curvol[gus.voice]);
  64.153 +                        break;
  64.154 +
  64.155 +                        case 0xA: /*Current addr high*/
  64.156 +                        gus.cur[gus.voice]=(gus.cur[gus.voice]&0x1F00FFFF)|(val<<16);
  64.157 +gus.curx[gus.voice]=(gus.curx[gus.voice]&0xF807F00)|((val<<7)<<8);
  64.158 +//                      gus.cur[gus.voice]=(gus.cur[gus.voice]&0x0F807F00)|((val<<7)<<8);
  64.159 +//                        printf("Write %i cur %08X\n",gus.voice,gus.cur[gus.voice],gus.curx[gus.voice]);
  64.160 +                        break;
  64.161 +                        case 0xB: /*Current addr low*/
  64.162 +                        gus.cur[gus.voice]=(gus.cur[gus.voice]&0x1FFFFF00)|val;
  64.163 +//                        printf("Write %i cur %08X\n",gus.voice,gus.cur[gus.voice],gus.curx[gus.voice]);
  64.164 +                        break;
  64.165 +
  64.166 +                        case 0x42: /*DMA address low*/
  64.167 +                        gus.dmaaddr=(gus.dmaaddr&0xFF000)|(val<<4);
  64.168 +                        break;
  64.169 +
  64.170 +                        case 0x43: /*Address low*/
  64.171 +                        gus.addr=(gus.addr&0xFFF00)|val;
  64.172 +                        break;
  64.173 +                        case 0x45: /*Timer control*/
  64.174 +//                        printf("Timer control %02X\n",val);
  64.175 +                        gus.tctrl=val;
  64.176 +                        break;
  64.177 +                }
  64.178 +                break;
  64.179 +                case 0x345: /*Global high*/
  64.180 +//                if (gus.global!=0x43 && gus.global!=0x44) printf("HWriting register %02X %02X %02X %04X:%04X\n",gus.global,gus.voice,val,CS,pc);
  64.181 +                switch (gus.global)
  64.182 +                {
  64.183 +                        case 0: /*Voice control*/
  64.184 +                        if (!(val&1) && gus.ctrl[gus.voice]&1)
  64.185 +                        {
  64.186 +//                                printf("Voice on %i - start %05X end %05X freq %04X\n",gus.voice,gus.start[gus.voice],gus.end[gus.voice],gus.freq[gus.voice]);
  64.187 +//                                if (val&0x40) gus.cur[gus.voice]=gus.end[gus.voice]<<8;
  64.188 +//                                else          gus.cur[gus.voice]=gus.start[gus.voice]<<8;
  64.189 +                        }
  64.190 +                        if (val&2) val|=1;
  64.191 +                        gus.waveirqs[gus.voice]=val&0x80;
  64.192 +                        gus.ctrl[gus.voice]=val&0x7F;
  64.193 +                        pollgusirqs();
  64.194 +                        break;
  64.195 +                        case 1: /*Frequency control*/
  64.196 +                        gus.freq[gus.voice]=(gus.freq[gus.voice]&0xFF)|(val<<8);
  64.197 +                        break;
  64.198 +                        case 2: /*Start addr high*/
  64.199 +                        gus.startx[gus.voice]=(gus.startx[gus.voice]&0x07FFF)|(val<<15);
  64.200 +                        gus.start[gus.voice]=(gus.start[gus.voice]&0x00FFFFFF)|((val&0x1F)<<24);
  64.201 +//                        printf("Write %i start %08X %08X %02X\n",gus.voice,gus.start[gus.voice],gus.startx[gus.voice],val);
  64.202 +                        break;
  64.203 +                        case 3: /*Start addr low*/
  64.204 +                        gus.startx[gus.voice]=(gus.startx[gus.voice]&0xFFF80)|(val&0x7F);
  64.205 +                        gus.start[gus.voice]=(gus.start[gus.voice]&0x1FFF00FF)|(val<<8);
  64.206 +//                        printf("Write %i start %08X %08X\n",gus.voice,gus.start[gus.voice],gus.startx[gus.voice]);
  64.207 +                        break;
  64.208 +                        case 4: /*End addr high*/
  64.209 +                        gus.endx[gus.voice]=(gus.endx[gus.voice]&0x07FFF)|(val<<15);
  64.210 +                        gus.end[gus.voice]=(gus.end[gus.voice]&0x00FFFFFF)|((val&0x1F)<<24);
  64.211 +//                        printf("Write %i end %08X %08X %02X\n",gus.voice,gus.end[gus.voice],gus.endx[gus.voice],val);
  64.212 +                        break;
  64.213 +                        case 5: /*End addr low*/
  64.214 +                        gus.endx[gus.voice]=(gus.endx[gus.voice]&0xFFF80)|(val&0x7F);
  64.215 +                        gus.end[gus.voice]=(gus.end[gus.voice]&0x1FFF00FF)|(val<<8);
  64.216 +//                        printf("Write %i end %08X %08X\n",gus.voice,gus.end[gus.voice],gus.endx[gus.voice]);
  64.217 +                        break;
  64.218 +
  64.219 +                        case 0x6: /*Ramp frequency*/
  64.220 +                        gus.rfreq[gus.voice] = (int)( (double)((val & 63)*512)/(double)(1 << (3*(val >> 6))));
  64.221 +//                        printf("RFREQ %02X %i %i %f %i\n",val,gus.voice,gus.rfreq[gus.voice],(double)(val & 63)/(double)(1 << (3*(val >> 6))),ins);
  64.222 +                        break;
  64.223 +                        case 0x7: /*Ramp start*/
  64.224 +                        gus.rstart[gus.voice]=val<<17;
  64.225 +                        break;
  64.226 +                        case 0x8: /*Ramp end*/
  64.227 +                        gus.rend[gus.voice]=val<<17;
  64.228 +                        break;
  64.229 +                        case 0x9: /*Current volume*/
  64.230 +                        gus.curvol[gus.voice]=gus.rcur[gus.voice]=(gus.rcur[gus.voice]&0x1FE00)|(val<<17);
  64.231 +//                        printf("Vol %i is %04X\n",gus.voice,gus.curvol[gus.voice]);
  64.232 +                        break;
  64.233 +
  64.234 +                        case 0xA: /*Current addr high*/
  64.235 +                        gus.cur[gus.voice]=(gus.cur[gus.voice]&0x00FFFFFF)|((val&0x1F)<<24);
  64.236 +gus.curx[gus.voice]=(gus.curx[gus.voice]&0x07FFF00)|((val<<15)<<8);
  64.237 +//                        printf("Write %i cur %08X %08X %02X\n",gus.voice,gus.cur[gus.voice],gus.curx[gus.voice],val);
  64.238 +//                      gus.cur[gus.voice]=(gus.cur[gus.voice]&0x007FFF00)|((val<<15)<<8);
  64.239 +                        break;
  64.240 +                        case 0xB: /*Current addr low*/
  64.241 +                        gus.cur[gus.voice]=(gus.cur[gus.voice]&0x1FFF00FF)|(val<<8);
  64.242 +gus.curx[gus.voice]=(gus.curx[gus.voice]&0xFFF8000)|((val&0x7F)<<8);
  64.243 +//                      gus.cur[gus.voice]=(gus.cur[gus.voice]&0x0FFF8000)|((val&0x7F)<<8);
  64.244 +//                        printf("Write %i cur %08X %08X\n",gus.voice,gus.cur[gus.voice],gus.curx[gus.voice]);
  64.245 +                        break;
  64.246 +                        case 0xD: /*Ramp control*/
  64.247 +                        if (val&2) val|=1;
  64.248 +                        gus.rampirqs[gus.voice]=val&0x80;
  64.249 +                        gus.rctrl[gus.voice]=val&0x7F;
  64.250 +                        pollgusirqs();
  64.251 +//                        printf("Ramp control %02i %02X %02X %i\n",gus.voice,val,gus.rampirqs[gus.voice],ins);
  64.252 +                        break;
  64.253 +
  64.254 +                        case 0xE:
  64.255 +                        gus.voices=(val&63)+1;
  64.256 +                        if (gus.voices>32) gus.voices=32;
  64.257 +                        if (gus.voices<14) gus.voices=14;
  64.258 +                        gus.global=val;
  64.259 +//                        printf("GUS voices %i\n",val&31);
  64.260 +                        break;
  64.261 +
  64.262 +                        case 0x41: /*DMA*/
  64.263 +                        if (val&1)
  64.264 +                        {
  64.265 +//                                printf("DMA start! %05X %02X\n",gus.dmaaddr,val);
  64.266 +                                c=0;
  64.267 +                                while (c<65536)
  64.268 +                                {
  64.269 +                                        d=readdma3();
  64.270 +                                        if (d==-1) break;
  64.271 +                                        if (val&0x80) d^=0x80;
  64.272 +                                        gusram[gus.dmaaddr]=d;
  64.273 +                                        gus.dmaaddr++;
  64.274 +                                        gus.dmaaddr&=0xFFFFF;
  64.275 +                                        c++;
  64.276 +                                }
  64.277 +//                                printf("Transferred %i bytes\n",c);
  64.278 +                                gus.dmactrl=val&~0x40;
  64.279 +                                if (val&0x20) gusirqnext=1;
  64.280 +//                                exit(-1);
  64.281 +                        }
  64.282 +                        break;
  64.283 +
  64.284 +                        case 0x42: /*DMA address low*/
  64.285 +                        gus.dmaaddr=(gus.dmaaddr&0xFF0)|(val<<12);
  64.286 +                        break;
  64.287 +
  64.288 +                        case 0x43: /*Address low*/
  64.289 +                        gus.addr=(gus.addr&0xF00FF)|(val<<8);
  64.290 +                        break;
  64.291 +                        case 0x44: /*Address high*/
  64.292 +                        gus.addr=(gus.addr&0xFFFF)|((val<<16)&0xF0000);
  64.293 +                        break;
  64.294 +                        case 0x45: /*Timer control*/
  64.295 +                        if (!(val&4)) gus.irqstatus&=~4;
  64.296 +                        if (!(val&8)) gus.irqstatus&=~8;
  64.297 +//                        printf("Timer control %02X\n",val);
  64.298 +/*                        if ((val&4) && !(gus.tctrl&4))
  64.299 +                        {
  64.300 +                                gus.t1=gus.t1l;
  64.301 +                                gus.t1on=1;
  64.302 +                        }*/
  64.303 +                        gus.tctrl=val;
  64.304 +                        break;
  64.305 +                        case 0x46: /*Timer 1*/
  64.306 +                        gus.t1=gus.t1l=val;
  64.307 +                        gus.t1on=1;
  64.308 +//                        printf("GUS timer 1 %i\n",val);
  64.309 +                        break;
  64.310 +                        case 0x47: /*Timer 2*/
  64.311 +                        gus.t2=gus.t2l=val<<2;
  64.312 +                        gus.t2on=1;
  64.313 +//                        printf("GUS timer 2 %i\n",val);
  64.314 +                        break;
  64.315 +                }
  64.316 +                break;
  64.317 +                case 0x347: /*DRAM access*/
  64.318 +                gusram[gus.addr]=val;
  64.319 +//                pclog("GUS RAM write %05X %02X\n",gus.addr,val);
  64.320 +                gus.addr&=0xFFFFF;
  64.321 +                break;
  64.322 +                case 0x248: case 0x388: gus.adcommand=val; break;
  64.323 +        }
  64.324 +}
  64.325 +
  64.326 +uint8_t readgus(uint16_t addr)
  64.327 +{
  64.328 +        uint8_t val;
  64.329 +//        /*if (addr!=0x246) */printf("Read GUS %04X %04X(%06X):%04X %02X\n",addr,CS,cs,pc,gus.global);
  64.330 +//        output=3;
  64.331 +        switch (addr)
  64.332 +        {
  64.333 +                case 0x240: return 0;
  64.334 +                case 0x246: /*IRQ status*/
  64.335 +                val=gus.irqstatus;
  64.336 +//                printf("246 status %02X\n",val);
  64.337 +//                gus.irqstatus=0;
  64.338 +//                if (gus.irqstatus2==0xE0) picintc(0x20);
  64.339 +                return val;
  64.340 +                case 0x24A:
  64.341 +                return gus.adcommand;
  64.342 +                case 0x24B: case 0x24F: return 0;
  64.343 +                case 0x340: /*MIDI status*/
  64.344 +                case 0x341: /*MIDI data*/
  64.345 +                return 0;
  64.346 +                case 0x342: return gus.voice;
  64.347 +                case 0x343: return gus.global;
  64.348 +                case 0x344: /*Global low*/
  64.349 +//                /*if (gus.global!=0x43 && gus.global!=0x44) */printf("Reading register %02X %02X\n",gus.global,gus.voice);
  64.350 +                switch (gus.global)
  64.351 +                {
  64.352 +                        case 0x82: /*Start addr high*/
  64.353 +                        return gus.start[gus.voice]>>16;
  64.354 +                        case 0x83: /*Start addr low*/
  64.355 +                        return gus.start[gus.voice]&0xFF;
  64.356 +
  64.357 +                        case 0x89: /*Current volume*/
  64.358 +                        return gus.rcur[gus.voice]>>9;
  64.359 +                        case 0x8A: /*Current addr high*/
  64.360 +                        return gus.cur[gus.voice]>>16;
  64.361 +                        case 0x8B: /*Current addr low*/
  64.362 +                        return gus.cur[gus.voice]&0xFF;
  64.363 +
  64.364 +                        case 0x8F: /*IRQ status*/
  64.365 +                        val=gus.irqstatus2;
  64.366 +//                        pclog("Read IRQ status - %02X\n",val);
  64.367 +                        gus.rampirqs[gus.irqstatus2&0x1F]=0;
  64.368 +                        gus.waveirqs[gus.irqstatus2&0x1F]=0;
  64.369 +                        pollgusirqs();
  64.370 +                        return val;
  64.371 +                }
  64.372 +                //fatal("Bad GUS global low read %02X\n",gus.global);
  64.373 +                break;
  64.374 +                case 0x345: /*Global high*/
  64.375 +//                /*if (gus.global!=0x43 && gus.global!=0x44) */printf("HReading register %02X %02X\n",gus.global,gus.voice);
  64.376 +                switch (gus.global)
  64.377 +                {
  64.378 +                        case 0x80: /*Voice control*/
  64.379 +                        return gus.ctrl[gus.voice]|(gus.waveirqs[gus.voice]?0x80:0);
  64.380 +
  64.381 +                        case 0x82: /*Start addr high*/
  64.382 +                        return gus.start[gus.voice]>>24;
  64.383 +                        case 0x83: /*Start addr low*/
  64.384 +                        return gus.start[gus.voice]>>8;
  64.385 +
  64.386 +                        case 0x89: /*Current volume*/
  64.387 +                        return gus.rcur[gus.voice]>>17;
  64.388 +
  64.389 +                        case 0x8A: /*Current addr high*/
  64.390 +                        return gus.cur[gus.voice]>>24;
  64.391 +                        case 0x8B: /*Current addr low*/
  64.392 +                        return gus.cur[gus.voice]>>8;
  64.393 +
  64.394 +                        case 0x8D:
  64.395 +//                                pclog("Read ramp control %02X %08X %08X  %08X %08X\n",gus.rctrl[gus.voice]|(gus.rampirqs[gus.voice]?0x80:0),gus.rcur[gus.voice],gus.rfreq[gus.voice],gus.rstart[gus.voice],gus.rend[gus.voice]);
  64.396 +                        return gus.rctrl[gus.voice]|(gus.rampirqs[gus.voice]?0x80:0);
  64.397 +
  64.398 +                        case 0x8F: /*IRQ status*/
  64.399 +                        val=gus.irqstatus2;
  64.400 +//                        pclog("Read IRQ status - %02X\n",val);
  64.401 +                        gus.rampirqs[gus.irqstatus2&0x1F]=0;
  64.402 +                        gus.waveirqs[gus.irqstatus2&0x1F]=0;
  64.403 +                        pollgusirqs();
  64.404 +                        return val;
  64.405 +
  64.406 +                        case 0x41: /*DMA control*/
  64.407 +                        val=gus.dmactrl|((gus.irqstatus&0x80)?0x40:0);
  64.408 +                        gus.irqstatus&=~0x80;
  64.409 +                        return val;
  64.410 +                        case 0x45: /*Timer control*/
  64.411 +                        return gus.tctrl;
  64.412 +                        case 0x49: /*Sampling control*/
  64.413 +                        return 0;
  64.414 +                }
  64.415 +                //fatal("Bad GUS global high read %02X\n",gus.global);
  64.416 +                break;
  64.417 +                case 0x346: return 0;
  64.418 +                case 0x347: /*DRAM access*/
  64.419 +                val=gusram[gus.addr];
  64.420 +//                pclog("GUS RAM read %05X %02X\n",gus.addr,val);
  64.421 +//                output=3;
  64.422 +                gus.addr&=0xFFFFF;
  64.423 +                return val;
  64.424 +                case 0x349: return 0;
  64.425 +        }
  64.426 +//        printf("Bad GUS read %04X! %02X\n",addr,gus.global);
  64.427 +//        exit(-1);
  64.428 +        return 0;
  64.429 +}
  64.430 +
  64.431 +void pollgus()
  64.432 +{
  64.433 +        if (gus.t1on)
  64.434 +        {
  64.435 +                gus.t1++;
  64.436 +                if (gus.t1>=0xFF)
  64.437 +                {
  64.438 +//                        gus.t1on=0;
  64.439 +                        gus.t1=gus.t1l;
  64.440 +                        if (gus.tctrl&4)
  64.441 +                        {
  64.442 +                                picintlevel(0x20);
  64.443 +                                gus.irqstatus|=4;
  64.444 +//                                printf("GUS T1 IRQ!\n");
  64.445 +                        }
  64.446 +                }
  64.447 +        }
  64.448 +        if (gusirqnext)
  64.449 +        {
  64.450 +                gusirqnext=0;
  64.451 +                gus.irqstatus|=0x80;
  64.452 +                picintlevel(0x20);
  64.453 +        }
  64.454 +}
  64.455 +
  64.456 +void pollgus2()
  64.457 +{
  64.458 +        if (gus.t2on)
  64.459 +        {
  64.460 +                gus.t2++;
  64.461 +                if (gus.t2>=(0xFF<<2))
  64.462 +                {
  64.463 +//                        gus.t2on=0;
  64.464 +                        gus.t2=gus.t2l;
  64.465 +                        if (gus.tctrl&8)
  64.466 +                        {
  64.467 +                                picintlevel(0x20);
  64.468 +                                gus.irqstatus|=8;
  64.469 +//                                printf("GUS T2 IRQ!\n");
  64.470 +                        }
  64.471 +                }
  64.472 +        }
  64.473 +        if (gusirqnext)
  64.474 +        {
  64.475 +                gusirqnext=0;
  64.476 +                gus.irqstatus|=0x80;
  64.477 +                picintlevel(0x20);
  64.478 +        }
  64.479 +}
  64.480 +
  64.481 +float gusfreqs[]=
  64.482 +{
  64.483 +        44100,41160,38587,36317,34300,32494,30870,29400,28063,26843,25725,24696,
  64.484 +        23746,22866,22050,21289,20580,19916,19293
  64.485 +};
  64.486 +
  64.487 +int16_t gusbufferx[65536];
  64.488 +int guspos=0;
  64.489 +void getgus(int16_t *p, int count)
  64.490 +{
  64.491 +        memcpy(p,gusbufferx,count*4);
  64.492 +//        printf("Get %i samples %i\n",guspos,count);
  64.493 +        guspos=0;
  64.494 +        pollgusirqs();
  64.495 +}
  64.496 +
  64.497 +void pollgussamp()
  64.498 +{
  64.499 +        uint32_t addr;
  64.500 +        int c,d;
  64.501 +        int16_t v;
  64.502 +        int32_t vl;
  64.503 +        int16_t p[2];
  64.504 +        float GUSRATECONST;
  64.505 +        if (guspos>65500) return;
  64.506 +//        return;
  64.507 +        if (gus.voices<14) GUSRATECONST=44100.0/48000.0;
  64.508 +        else               GUSRATECONST=gusfreqs[gus.voices-14]/48000.0;
  64.509 +//        printf("Voices %i freq %f\n",gus.voices,GUSRATECONST*48000.0);
  64.510 +//        for (c=0;c<count;c++)
  64.511 +//        {
  64.512 +                p[0]=p[1]=0;
  64.513 +                for (d=0;d<32;d++)
  64.514 +                {
  64.515 +                        if (!(gus.ctrl[d]&1))
  64.516 +                        {
  64.517 +                                if (gus.ctrl[d]&4)
  64.518 +                                {
  64.519 +                                        addr=gus.cur[d]>>9;
  64.520 +                                        addr=(addr&0xC0000)|((addr<<1)&0x3FFFE);
  64.521 +                                        if (!(gus.freq[d]>>10)) /*Interpolate*/
  64.522 +                                        {
  64.523 +                                                vl=(int16_t)(int8_t)((gusram[(addr+1)&0xFFFFF]^0x80)-0x80)*(511-(gus.cur[d]&511));
  64.524 +                                                vl+=(int16_t)(int8_t)((gusram[(addr+3)&0xFFFFF]^0x80)-0x80)*(gus.cur[d]&511);
  64.525 +                                                v=vl>>9;
  64.526 +                                        }
  64.527 +                                        else
  64.528 +                                           v=(int16_t)(int8_t)((gusram[(addr+1)&0xFFFFF]^0x80)-0x80);
  64.529 +                                }
  64.530 +                                else
  64.531 +                                {
  64.532 +                                        if (!(gus.freq[d]>>10)) /*Interpolate*/
  64.533 +                                        {
  64.534 +                                                vl=((int8_t)((gusram[(gus.cur[d]>>9)&0xFFFFF]^0x80)-0x80))*(511-(gus.cur[d]&511));
  64.535 +                                                vl+=((int8_t)((gusram[((gus.cur[d]>>9)+1)&0xFFFFF]^0x80)-0x80))*(gus.cur[d]&511);
  64.536 +                                                v=vl>>9;
  64.537 +                                        }
  64.538 +                                        else
  64.539 +                                           v=(int16_t)(int8_t)((gusram[(gus.cur[d]>>9)&0xFFFFF]^0x80)-0x80);
  64.540 +                                }
  64.541 +//                                   v=(int16_t)((float)((gusram[(gus.cur[d]>>9)&0xFFFFF]^0x80)-0x80)*32.0*vol16bit[(gus.rcur[d]>>13)&4095]);
  64.542 +                                if ((gus.rcur[d]>>13)>4095) v=(int16_t)(float)(v)*24.0*vol16bit[4095];
  64.543 +                                else                        v=(int16_t)(float)(v)*24.0*vol16bit[(gus.rcur[d]>>13)&4095];
  64.544 +//                                if (!d) printf("%08X  %08X %08X  %05X  %08X %08X  %04X %f %04X %08X %i\n",gus.cur[d],gus.start[d],gus.end[d],gus.cur[d]>>9,gus.startx[d],gus.endx[d],gus.rcur[d],vol16bit[0],v,gus.freq[d],ins);
  64.545 +//                                if (!d)
  64.546 +//                                {
  64.547 +                                        p[0]+=v;
  64.548 +                                        p[1]+=v;
  64.549 +//                                }
  64.550 +//                                printf("Data from %08X\n",gus.cur[d]>>8);
  64.551 +                                if (gus.ctrl[d]&0x40)
  64.552 +                                {
  64.553 +                                        gus.cur[d]-=(gus.freq[d]>>1)*GUSRATECONST;
  64.554 +                                        if (gus.cur[d]<=gus.start[d])
  64.555 +                                        {
  64.556 +                                                if (!(gus.rctrl[d]&4))
  64.557 +                                                {
  64.558 +                                                        if (!(gus.ctrl[d]&8)) gus.ctrl[d]|=1;
  64.559 +                                                        else if (gus.ctrl[d]&0x10) gus.ctrl[d]^=0x40;
  64.560 +                                                        gus.cur[d]=(gus.ctrl[d]&0x40)?gus.end[d]:gus.start[d];
  64.561 +                                                }
  64.562 +                                                if (gus.ctrl[d]&0x20) gus.waveirqs[d]=1;
  64.563 +                                        }
  64.564 +                                }
  64.565 +                                else
  64.566 +                                {
  64.567 +                                        gus.cur[d]+=(gus.freq[d]>>1)*GUSRATECONST;
  64.568 +//                                        pclog("GUS add %08X %f\n",gus.freq[d],GUSRATECONST);
  64.569 +                                        if (gus.cur[d]>=gus.end[d])
  64.570 +                                        {
  64.571 +                                                if (!(gus.rctrl[d]&4))
  64.572 +                                                {
  64.573 +//                                                        gus.ctrl[d]|=1;
  64.574 +                                                        if (!(gus.ctrl[d]&8)) gus.ctrl[d]|=1;
  64.575 +                                                        else if (gus.ctrl[d]&0x10) gus.ctrl[d]^=0x40;
  64.576 +                                                        gus.cur[d]=(gus.ctrl[d]&0x40)?gus.end[d]:gus.start[d];
  64.577 +                                                }
  64.578 +                                                if (gus.ctrl[d]&0x20) gus.waveirqs[d]=1;
  64.579 +                                        }
  64.580 +                                }
  64.581 +                        }
  64.582 +                        if (!(gus.rctrl[d]&1))
  64.583 +                        {
  64.584 +                                if (gus.rctrl[d]&0x40)
  64.585 +                                {
  64.586 +                                        gus.rcur[d]-=gus.rfreq[d]*GUSRATECONST*16;
  64.587 +//                                        printf("RCUR- %i %i %i %i %i\n",d,gus.rfreq[d],gus.rcur[d],gus.rstart[d],gus.rend[d]);
  64.588 +                                        if (gus.rcur[d]<=gus.rstart[d])
  64.589 +                                        {
  64.590 +                                                if (gus.rctrl[d]&8)    gus.rcur[d]=gus.rend[d]<<8;
  64.591 +                                                else                   gus.rctrl[d]|=1;
  64.592 +                                                if (gus.rctrl[d]&0x20)
  64.593 +                                                {
  64.594 +                                                        gus.rampirqs[d]=1;
  64.595 +//                                                        pclog("Causing ramp IRQ %02X\n",gus.rctrl[d]);
  64.596 +                                                }
  64.597 +                                        }
  64.598 +                                }
  64.599 +                                else
  64.600 +                                {
  64.601 +                                        gus.rcur[d]+=gus.rfreq[d]*GUSRATECONST*16;
  64.602 +//                                        printf("RCUR+ %i %08X %08X %08X %08X\n",d,gus.rfreq[d],gus.rcur[d],gus.rstart[d],gus.rend[d]);
  64.603 +                                        if (gus.rcur[d]>=gus.rend[d])
  64.604 +                                        {
  64.605 +                                                if (gus.rctrl[d]&8) gus.rcur[d]=gus.rstart[d]<<8;
  64.606 +                                                else                gus.rctrl[d]|=1;
  64.607 +                                                if (gus.rctrl[d]&0x20)
  64.608 +                                                {
  64.609 +                                                        gus.rampirqs[d]=1;
  64.610 +//                                                        pclog("Causing ramp IRQ %02X\n",gus.rctrl[d]);
  64.611 +                                                }
  64.612 +                                        }
  64.613 +                                }
  64.614 +                        }
  64.615 +                }
  64.616 +                gusbufferx[guspos++]=p[0];
  64.617 +                gusbufferx[guspos++]=p[1];
  64.618 +                if (guspos==65536) guspos=0;
  64.619 +//        }
  64.620 +        pollgusirqs();
  64.621 +}
  64.622 +
  64.623 +void gus_init()
  64.624 +{
  64.625 +        io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL);
  64.626 +        io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL);
  64.627 +        io_sethandler(0x0388, 0x0001, NULL,    NULL, NULL, writegus, NULL, NULL);
  64.628 +}
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/src/harddisk.c	Sun Apr 21 14:54:35 2013 +0100
    65.3 @@ -0,0 +1,155 @@
    65.4 +/*Due to the lack of a real hard disc BIOS (other than the WD ST-506 one in MESS),
    65.5 +  I wrote this. It's better as it can handle bigger discs, but is (potentially)
    65.6 +  less compatible.*/
    65.7 +#include <stdio.h>
    65.8 +#include <string.h>
    65.9 +#include "ibm.h"
   65.10 +
   65.11 +extern int output;
   65.12 +void inithdc()
   65.13 +{
   65.14 +        return;
   65.15 +        hdc[0].f=romfopen("hdc.img","rb+");
   65.16 +        if (!hdc[0].f)
   65.17 +        {
   65.18 +                hdc[0].f=romfopen("hdc.img","wb");
   65.19 +                putc(0,hdc[0].f);
   65.20 +                fclose(hdc[0].f);
   65.21 +                hdc[0].f=romfopen("hdc.img","rb+");
   65.22 +        }
   65.23 +//        hdc[0].spt=16;
   65.24 +//        hdc[0].hpc=5;
   65.25 +//        hdc[0].tracks=977;
   65.26 +
   65.27 +        hdc[1].f=romfopen("hdd.img","rb+");
   65.28 +        if (!hdc[1].f)
   65.29 +        {
   65.30 +                hdc[1].f=romfopen("hdd.img","wb");
   65.31 +                putc(0,hdc[1].f);
   65.32 +                fclose(hdc[1].f);
   65.33 +                hdc[1].f=romfopen("hdd.img","rb+");
   65.34 +        }
   65.35 +//        hdc[1].spt=32;
   65.36 +//        hdc[1].hpc=16;
   65.37 +//        hdc[1].tracks=447;
   65.38 +}
   65.39 +
   65.40 +void int13hdc()
   65.41 +{
   65.42 +        int drv=DL&1;
   65.43 +        int track,head,sector;
   65.44 +        uint32_t addr;
   65.45 +        int c,d;
   65.46 +        uint8_t buf[512];
   65.47 +        fullspeed();
   65.48 +//        ram[0x475]=2;
   65.49 +//        printf("INT 13 HDC %04X %04X %04X %04X  %04X:%04X\n",AX,BX,CX,DX,CS,pc);
   65.50 +        switch (AH)
   65.51 +        {
   65.52 +                case 0: /*Reset disk system*/
   65.53 +                AH=0;
   65.54 +                flags&=~C_FLAG;
   65.55 +                break;
   65.56 +                case 2: /*Read sectors into memory*/
   65.57 +//                printf("Read %i sectors to %04X:%04X\n",AL,es>>4,BX);
   65.58 +//                if (es==0xf940) output=3;
   65.59 +                track=CH|((CL&0xC0)<<2);
   65.60 +                sector=(CL&63)-1;
   65.61 +                head=DH;
   65.62 +                addr=((((track*hdc[drv].hpc)+head)*hdc[drv].spt)+sector)*512;
   65.63 +//                printf("Read track %i head %i sector %i addr %08X  HPC %i SPT %i %08X\n",track,head,sector,addr,hdc[drv].hpc,hdc[drv].spt,old8);
   65.64 +                fseek(hdc[drv].f,addr,SEEK_SET);
   65.65 +                for (c=0;c<AL;c++)
   65.66 +                {
   65.67 +                        fread(buf,512,1,hdc[drv].f);
   65.68 +                        for (d=0;d<512;d++)
   65.69 +                        {
   65.70 +                                writemembl(es+BX+(c*512)+d,buf[d]/*getc(hdc[drv].f)*/);
   65.71 +                        }
   65.72 +                }
   65.73 +                AH=0;
   65.74 +                flags&=~C_FLAG;
   65.75 +                readflash=1;
   65.76 +                break;
   65.77 +                case 3: /*Write sectors*/
   65.78 +                track=CH|((CL&0xC0)<<2);
   65.79 +                sector=(CL&63)-1;
   65.80 +                head=DH;
   65.81 +                addr=((((track*hdc[drv].hpc)+head)*hdc[drv].spt)+sector)*512;
   65.82 +                fseek(hdc[drv].f,addr,SEEK_SET);
   65.83 +                for (c=0;c<AL;c++)
   65.84 +                {
   65.85 +                        for (d=0;d<512;d++)
   65.86 +                        {
   65.87 +                                putc(readmembl(es+BX+(c*512)+d),hdc[drv].f);
   65.88 +                        }
   65.89 +                }
   65.90 +                AH=0;
   65.91 +                flags&=~C_FLAG;
   65.92 +                readflash=1;
   65.93 +                break;
   65.94 +                case 4: /*Verify sectors*/
   65.95 +                AH=0; /*We don't actually do anything here*/
   65.96 +                flags&=~C_FLAG;
   65.97 +                break;
   65.98 +                case 8: /*Get drive parameters*/
   65.99 +                AH=0;
  65.100 +                CH=hdc[drv].tracks&255;
  65.101 +                CL=hdc[drv].spt;
  65.102 +                CL|=((hdc[drv].tracks>>2)&0xC0);
  65.103 +//                printf("Drive params - %02X %02X %i %i\n",CL,CH,hdc[drv].tracks,hdc[drv].spt);
  65.104 +                DH=hdc[drv].hpc-1;
  65.105 +                DL=2;
  65.106 +                flags&=~C_FLAG;
  65.107 +                break;
  65.108 +                case 0x10: /*Check drive ready*/
  65.109 +                AH=0;
  65.110 +                flags&=~C_FLAG;
  65.111 +                break;
  65.112 +                case 0x18: /*Set media type*/
  65.113 +                AH=1;
  65.114 +                flags|=C_FLAG;
  65.115 +                break;
  65.116 +                
  65.117 +                default:
  65.118 +                        AH=1;
  65.119 +                        flags|=C_FLAG;
  65.120 +//                printf("Bad HDC int 13 %04X\n",AX);
  65.121 +//                dumpregs();
  65.122 +//                exit(-1);
  65.123 +        }
  65.124 +}
  65.125 +
  65.126 +char tempbuf[512*63];
  65.127 +void resizedrive(int drv)
  65.128 +{
  65.129 +        FILE *f;
  65.130 +        int c,d,e;
  65.131 +//        char temp[512*63];
  65.132 +        if (!drv)
  65.133 +        {
  65.134 +                fflush(hdc[0].f);
  65.135 +                if (hdc[0].f) fclose(hdc[0].f);
  65.136 +                f=romfopen("hdc.img","wb");
  65.137 +        }
  65.138 +        else
  65.139 +        {
  65.140 +                fflush(hdc[1].f);
  65.141 +                if (hdc[1].f) fclose(hdc[1].f);
  65.142 +                f=romfopen("hdd.img","wb");
  65.143 +        }
  65.144 +        memset(tempbuf,0,512*63);
  65.145 +        for (c=0;c<hdc[drv].tracks;c++)
  65.146 +        {
  65.147 +                for (d=0;d<hdc[drv].hpc;d++)
  65.148 +                {
  65.149 +//                        for (e=0;e<hdc[drv].spt;e++)
  65.150 +//                        {
  65.151 +                                fwrite(tempbuf,512*hdc[drv].spt,1,f);
  65.152 +//                        }
  65.153 +                }
  65.154 +        }
  65.155 +        fclose(f);
  65.156 +        if (!drv) hdc[0].f=romfopen("hdc.img","rb+");
  65.157 +        else      hdc[1].f=romfopen("hdd.img","rb+");
  65.158 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/src/headland.c	Sun Apr 21 14:54:35 2013 +0100
    66.3 @@ -0,0 +1,45 @@
    66.4 +#include "ibm.h"
    66.5 +#include "io.h"
    66.6 +#include "mem.h"
    66.7 +#include "cpu.h"
    66.8 +
    66.9 +#include "headland.h"
   66.10 +
   66.11 +static int headland_index;
   66.12 +static uint8_t headland_regs[256];
   66.13 +
   66.14 +void headland_write(uint16_t addr, uint8_t val)
   66.15 +{
   66.16 +        if (addr & 1)
   66.17 +        {
   66.18 +                if (headland_index == 0xc1 && !is486) val = 0;
   66.19 +                headland_regs[headland_index] = val;
   66.20 +                pclog("Headland write %02X %02X\n",headland_index,val);
   66.21 +                if (headland_index == 0x82)
   66.22 +                {
   66.23 +                        shadowbios = val & 0x10;
   66.24 +                        shadowbios_write = !(val & 0x10);
   66.25 +                        if (shadowbios)
   66.26 +                           mem_sethandler(0xf0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    NULL,          NULL,           NULL          );
   66.27 +                        else
   66.28 +                           mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml);
   66.29 +                }
   66.30 +        }
   66.31 +        else          headland_index = val;
   66.32 +}
   66.33 +
   66.34 +uint8_t headland_read(uint16_t addr)
   66.35 +{
   66.36 +        if (addr & 1) 
   66.37 +        {
   66.38 +                if ((headland_index >= 0xc0 || headland_index == 0x20) && cpu_iscyrix)
   66.39 +                   return 0xff; /*Don't conflict with Cyrix config registers*/
   66.40 +                return headland_regs[headland_index];
   66.41 +        }
   66.42 +        return headland_index;
   66.43 +}
   66.44 +
   66.45 +void headland_init()
   66.46 +{
   66.47 +        io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL);
   66.48 +}
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/src/headland.h	Sun Apr 21 14:54:35 2013 +0100
    67.3 @@ -0,0 +1,1 @@
    67.4 +void headland_init();
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/src/ibm.h	Sun Apr 21 14:54:35 2013 +0100
    68.3 @@ -0,0 +1,468 @@
    68.4 +#include <stdio.h>
    68.5 +#include <stdint.h>
    68.6 +#define printf pclog
    68.7 +
    68.8 +/*Memory*/
    68.9 +uint8_t *ram,*vram;
   68.10 +
   68.11 +unsigned char isram[0x10000];
   68.12 +
   68.13 +uint32_t rammask;
   68.14 +
   68.15 +int readlookup[256],readlookupp[256];
   68.16 +uint32_t *readlookup2;
   68.17 +int readlnext;
   68.18 +int writelookup[256],writelookupp[256];
   68.19 +uint32_t *writelookup2;
   68.20 +int writelnext;
   68.21 +
   68.22 +extern int mmu_perm;
   68.23 +
   68.24 +#define readmemb(a) ((readlookup2[(a)>>12]==0xFFFFFFFF)?readmembl(a):ram[readlookup2[(a)>>12]+((a)&0xFFF)])
   68.25 +#define readmemw(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE)?readmemwl(s,a):*((uint16_t *)(&ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)])))
   68.26 +#define readmeml(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC)?readmemll(s,a):*((uint32_t *)(&ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)])))
   68.27 +
   68.28 +//#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v
   68.29 +//#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
   68.30 +//#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
   68.31 +//#define readmemb(a) ((isram[((a)>>16)&255] && !(cr0>>31))?ram[a&0xFFFFFF]:readmembl(a))
   68.32 +//#define writememb(a,v) if (isram[((a)>>16)&255] && !(cr0>>31)) ram[a&0xFFFFFF]=v; else writemembl(a,v)
   68.33 +
   68.34 +//void writememb(uint32_t addr, uint8_t val);
   68.35 +uint8_t readmembl(uint32_t addr);
   68.36 +void writemembl(uint32_t addr, uint8_t val);
   68.37 +uint8_t readmemb386l(uint32_t seg, uint32_t addr);
   68.38 +void writememb386l(uint32_t seg, uint32_t addr, uint8_t val);
   68.39 +uint16_t readmemwl(uint32_t seg, uint32_t addr);
   68.40 +void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
   68.41 +uint32_t readmemll(uint32_t seg, uint32_t addr);
   68.42 +void writememll(uint32_t seg, uint32_t addr, uint32_t val);
   68.43 +
   68.44 +uint8_t *getpccache(uint32_t a);
   68.45 +
   68.46 +uint32_t mmutranslatereal(uint32_t addr, int rw);
   68.47 +
   68.48 +void addreadlookup(uint32_t virt, uint32_t phys);
   68.49 +void addwritelookup(uint32_t virt, uint32_t phys);
   68.50 +
   68.51 +
   68.52 +/*IO*/
   68.53 +uint8_t  inb(uint16_t port);
   68.54 +void outb(uint16_t port, uint8_t  val);
   68.55 +uint16_t inw(uint16_t port);
   68.56 +void outw(uint16_t port, uint16_t val);
   68.57 +uint32_t inl(uint16_t port);
   68.58 +void outl(uint16_t port, uint32_t val);
   68.59 +
   68.60 +FILE *romfopen(char *fn, char *mode);
   68.61 +extern int shadowbios,shadowbios_write;
   68.62 +extern int cache;
   68.63 +extern int mem_size;
   68.64 +extern int readlnum,writelnum;
   68.65 +extern int memwaitstate;
   68.66 +
   68.67 +
   68.68 +/*Processor*/
   68.69 +#define EAX regs[0].l
   68.70 +#define ECX regs[1].l
   68.71 +#define EDX regs[2].l
   68.72 +#define EBX regs[3].l
   68.73 +#define ESP regs[4].l
   68.74 +#define EBP regs[5].l
   68.75 +#define ESI regs[6].l
   68.76 +#define EDI regs[7].l
   68.77 +#define AX regs[0].w
   68.78 +#define CX regs[1].w
   68.79 +#define DX regs[2].w
   68.80 +#define BX regs[3].w
   68.81 +#define SP regs[4].w
   68.82 +#define BP regs[5].w
   68.83 +#define SI regs[6].w
   68.84 +#define DI regs[7].w
   68.85 +#define AL regs[0].b.l
   68.86 +#define AH regs[0].b.h
   68.87 +#define CL regs[1].b.l
   68.88 +#define CH regs[1].b.h
   68.89 +#define DL regs[2].b.l
   68.90 +#define DH regs[2].b.h
   68.91 +#define BL regs[3].b.l
   68.92 +#define BH regs[3].b.h
   68.93 +
   68.94 +typedef union
   68.95 +{
   68.96 +        uint32_t l;
   68.97 +        uint16_t w;
   68.98 +        struct
   68.99 +        {
  68.100 +                uint8_t l,h;
  68.101 +        } b;
  68.102 +} x86reg;
  68.103 +
  68.104 +x86reg regs[8];
  68.105 +uint16_t flags,eflags;
  68.106 +uint32_t /*cs,ds,es,ss,*/oldds,oldss,pc,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
  68.107 +//uint16_t msw;
  68.108 +
  68.109 +extern int ins,output;
  68.110 +extern int cycdiff;
  68.111 +
  68.112 +typedef struct
  68.113 +{
  68.114 +        uint32_t base;
  68.115 +        uint32_t limit,limitw;
  68.116 +        uint8_t access;
  68.117 +        uint16_t seg;
  68.118 +} x86seg;
  68.119 +
  68.120 +x86seg gdt,ldt,idt,tr;
  68.121 +x86seg _cs,_ds,_es,_ss,_fs,_gs;
  68.122 +x86seg _oldds;
  68.123 +
  68.124 +uint32_t pccache;
  68.125 +uint8_t *pccache2;
  68.126 +/*Segments -
  68.127 +  _cs,_ds,_es,_ss are the segment structures
  68.128 +  CS,DS,ES,SS is the 16-bit data
  68.129 +  cs,ds,es,ss are defines to the bases*/
  68.130 +//uint16_t CS,DS,ES,SS;
  68.131 +#define CS _cs.seg
  68.132 +#define DS _ds.seg
  68.133 +#define ES _es.seg
  68.134 +#define SS _ss.seg
  68.135 +#define FS _fs.seg
  68.136 +#define GS _gs.seg
  68.137 +#define cs _cs.base
  68.138 +#define ds _ds.base
  68.139 +#define es _es.base
  68.140 +#define ss _ss.base
  68.141 +#define fs _fs.base
  68.142 +#define gs _gs.base
  68.143 +
  68.144 +#define CPL ((_cs.access>>5)&3)
  68.145 +
  68.146 +void loadseg(uint16_t seg, x86seg *s);
  68.147 +void loadcs(uint16_t seg);
  68.148 +
  68.149 +union
  68.150 +{
  68.151 +        uint32_t l;
  68.152 +        uint16_t w;
  68.153 +} CR0;
  68.154 +
  68.155 +#define cr0 CR0.l
  68.156 +#define msw CR0.w
  68.157 +
  68.158 +uint32_t cr2,cr3;
  68.159 +
  68.160 +#define C_FLAG  0x0001
  68.161 +#define P_FLAG  0x0004
  68.162 +#define A_FLAG  0x0010
  68.163 +#define Z_FLAG  0x0040
  68.164 +#define N_FLAG  0x0080
  68.165 +#define T_FLAG  0x0100
  68.166 +#define I_FLAG  0x0200
  68.167 +#define D_FLAG  0x0400
  68.168 +#define V_FLAG  0x0800
  68.169 +#define NT_FLAG 0x4000
  68.170 +#define VM_FLAG 0x0002 /*In EFLAGS*/
  68.171 +
  68.172 +#define WP_FLAG 0x10000 /*In CR0*/
  68.173 +
  68.174 +#define IOPL ((flags>>12)&3)
  68.175 +
  68.176 +#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
  68.177 +//#define IOPLp 1
  68.178 +
  68.179 +//#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL))
  68.180 +extern int cycles;
  68.181 +extern int cycles_lost;
  68.182 +extern int is486;
  68.183 +extern uint8_t opcode;
  68.184 +extern int insc;
  68.185 +extern int fpucount;
  68.186 +extern float mips,flops;
  68.187 +extern int clockrate;
  68.188 +extern int cgate16;
  68.189 +extern int CPUID;
  68.190 +
  68.191 +extern int cpl_override;
  68.192 +
  68.193 +/*Timer*/
  68.194 +typedef struct PIT
  68.195 +{
  68.196 +        uint32_t l[3];
  68.197 +        double c[3];
  68.198 +        uint8_t m[3];
  68.199 +        uint8_t ctrl,ctrls[2];
  68.200 +        int wp,rm[3],wm[3];
  68.201 +        uint16_t rl[3];
  68.202 +        int thit[3];
  68.203 +        int delay[3];
  68.204 +        int rereadlatch[3];
  68.205 +} PIT;
  68.206 +
  68.207 +PIT pit;
  68.208 +void setpitclock(float clock);
  68.209 +int pitcount;
  68.210 +
  68.211 +float pit_timer0_freq();
  68.212 +
  68.213 +
  68.214 +
  68.215 +/*DMA*/
  68.216 +typedef struct DMA
  68.217 +{
  68.218 +        uint16_t ab[4],ac[4];
  68.219 +        uint16_t cb[4];
  68.220 +        int cc[4];
  68.221 +        int wp;
  68.222 +        uint8_t m,mode[4];
  68.223 +        uint8_t page[4];
  68.224 +        uint8_t stat;
  68.225 +        uint8_t command;
  68.226 +} DMA;
  68.227 +
  68.228 +DMA dma,dma16;
  68.229 +
  68.230 +
  68.231 +/*PPI*/
  68.232 +typedef struct PPI
  68.233 +{
  68.234 +        int s2;
  68.235 +        uint8_t pa,pb;
  68.236 +} PPI;
  68.237 +
  68.238 +PPI ppi;
  68.239 +extern int key_inhibit;
  68.240 +
  68.241 +
  68.242 +/*PIC*/
  68.243 +typedef struct PIC
  68.244 +{
  68.245 +        uint8_t icw1,mask,ins,pend,mask2;
  68.246 +        int icw;
  68.247 +        uint8_t vector;
  68.248 +        int read;
  68.249 +} PIC;
  68.250 +
  68.251 +PIC pic,pic2;
  68.252 +extern int pic_intpending;
  68.253 +int intcount;
  68.254 +
  68.255 +
  68.256 +/*FDC*/
  68.257 +typedef struct FDC
  68.258 +{
  68.259 +        uint8_t dor,stat,command,dat,st0;
  68.260 +        int head,track[256],sector,drive,lastdrive;
  68.261 +        int pos;
  68.262 +        uint8_t params[256];
  68.263 +        uint8_t res[256];
  68.264 +        int pnum,ptot;
  68.265 +        int rate;
  68.266 +        uint8_t specify[256];
  68.267 +        int eot[256];
  68.268 +        int lock;
  68.269 +        int perp;
  68.270 +        uint8_t config, pretrk;
  68.271 +} FDC;
  68.272 +
  68.273 +FDC fdc;
  68.274 +int disctime;
  68.275 +char discfns[2][256];
  68.276 +int driveempty[2];
  68.277 +
  68.278 +
  68.279 +/*Config stuff*/
  68.280 +#define MDA ((gfxcard==GFX_MDA || gfxcard==GFX_HERCULES) && (romset<ROM_TANDY || romset>=ROM_IBMAT))
  68.281 +#define HERCULES (gfxcard==GFX_HERCULES && (romset<ROM_TANDY || romset>=ROM_IBMAT))
  68.282 +#define AMSTRAD (romset==ROM_PC1512 || romset==ROM_PC1640 || romset==ROM_PC3086)
  68.283 +#define AMSTRADIO (romset==ROM_PC1512 || romset==ROM_PC1640 || romset==ROM_PC200 || romset==ROM_PC2086 || romset == ROM_PC3086)
  68.284 +#define TANDY (romset==ROM_TANDY/* || romset==ROM_IBMPCJR*/)
  68.285 +#define VID_EGA (gfxcard==GFX_EGA)
  68.286 +#define EGA (romset==ROM_PC1640 || VID_EGA || VGA)
  68.287 +#define VGA ((gfxcard>=GFX_TVGA || romset==ROM_ACER386) && romset!=ROM_PC1640 && romset!=ROM_PC1512 && romset!=ROM_TANDY && romset!=ROM_PC200)
  68.288 +#define SVGA (gfxcard==GFX_ET4000 && VGA)
  68.289 +#define TRIDENT (gfxcard==GFX_TVGA && !OTI067)
  68.290 +#define OTI067 (romset==ROM_ACER386)
  68.291 +#define ET4000 (gfxcard==GFX_ET4000 && VGA)
  68.292 +#define ET4000W32 (gfxcard==GFX_ET4000W32 && VGA)
  68.293 +#define AT (romset>=ROM_IBMAT)
  68.294 +#define PCI (romset == ROM_PCI486)
  68.295 +
  68.296 +#define AMIBIOS (romset==ROM_AMI386 || romset==ROM_AMI486 || romset == ROM_WIN486)
  68.297 +int FASTDISC;
  68.298 +int ADLIB;
  68.299 +int GAMEBLASTER;
  68.300 +
  68.301 +enum
  68.302 +{
  68.303 +        ROM_IBMPC = 0,  /*301 keyboard error, 131 cassette (!!!) error*/
  68.304 +        ROM_IBMXT,      /*301 keyboard error*/
  68.305 +        ROM_GENXT,      /*'Generic XT BIOS'*/
  68.306 +        ROM_DTKXT,
  68.307 +        ROM_EUROPC,
  68.308 +        ROM_OLIM24,
  68.309 +        ROM_TANDY,
  68.310 +        ROM_PC1512,
  68.311 +        ROM_PC200,
  68.312 +        ROM_PC1640,
  68.313 +        ROM_PC2086,
  68.314 +        ROM_PC3086,        
  68.315 +        ROM_IBMAT,
  68.316 +        ROM_CMDPC30,
  68.317 +        ROM_AMI286,
  68.318 +        ROM_DELL200,
  68.319 +        ROM_MISC286,
  68.320 +        ROM_IBMAT386,
  68.321 +        ROM_ACER386,
  68.322 +        ROM_MEGAPC,
  68.323 +        ROM_AMI386,
  68.324 +        ROM_AMI486,
  68.325 +        ROM_WIN486,
  68.326 +        ROM_PCI486
  68.327 +};
  68.328 +
  68.329 +//#define ROM_IBMPCJR 5 /*Not working! ROMs are corrupt*/
  68.330 +#define is386 (romset>=ROM_IBMAT386)
  68.331 +#define is386sx 0
  68.332 +
  68.333 +int hasfpu;
  68.334 +int romset;
  68.335 +
  68.336 +#define GFX_CGA 0
  68.337 +#define GFX_MDA 1
  68.338 +#define GFX_HERCULES 2
  68.339 +#define GFX_EGA 3     /*Using IBM EGA BIOS*/
  68.340 +//#define GFX_OTI067 3    /*Using BIOS from Acer 386SX/25N - edit - only works with Acer BIOS! Stupid integrated systems*/
  68.341 +#define GFX_TVGA 4      /*Using Trident 8900D BIOS*/
  68.342 +#define GFX_ET4000 5    /*Tseng ET4000*/
  68.343 +#define GFX_ET4000W32 6 /*Tseng ET4000/W32p (Diamond Stealth 32)*/
  68.344 +#define GFX_BAHAMAS64 7 /*S3 Vision864 (Paradise Bahamas 64)*/
  68.345 +#define GFX_N9_9FX    8 /*S3 764/Trio64 (Number Nine 9FX)*/
  68.346 +#define GFX_STEALTH64 9 /*S3 Vision964 (Diamond Stealth 64 VRAM PCI)*/
  68.347 +
  68.348 +int gfxcard;
  68.349 +
  68.350 +int cpuspeed;
  68.351 +
  68.352 +
  68.353 +/*Video*/
  68.354 +void (*pollvideo)();
  68.355 +void pollega();
  68.356 +int readflash;
  68.357 +uint8_t hercctrl;
  68.358 +int slowega,egacycles,egacycles2;
  68.359 +extern uint8_t gdcreg[16];
  68.360 +extern int incga;
  68.361 +extern int egareads,egawrites;
  68.362 +extern int cga_comp;
  68.363 +extern int vid_resize;
  68.364 +extern int winsizex,winsizey;
  68.365 +extern int chain4;
  68.366 +
  68.367 +uint8_t readvram(uint16_t addr);
  68.368 +void writevram(uint16_t addr, uint8_t val);
  68.369 +void writevramgen(uint16_t addr, uint8_t val);
  68.370 +
  68.371 +uint8_t readtandyvram(uint16_t addr);
  68.372 +void writetandy(uint16_t addr, uint8_t val);
  68.373 +void writetandyvram(uint16_t addr, uint8_t val);
  68.374 +
  68.375 +extern int et4k_b8000;
  68.376 +extern int changeframecount;
  68.377 +extern uint8_t changedvram[(8192*1024)/1024];
  68.378 +
  68.379 +void writeega_chain4(uint32_t addr, uint8_t val);
  68.380 +extern uint32_t svgarbank,svgawbank;
  68.381 +
  68.382 +/*Serial*/
  68.383 +extern int mousedelay;
  68.384 +
  68.385 +
  68.386 +/*Sound*/
  68.387 +uint8_t spkstat;
  68.388 +
  68.389 +float spktime,soundtime,gustime,gustime2,vidtime,rtctime;
  68.390 +int ppispeakon;
  68.391 +//#define SPKCONST (8000000.0/44100.0)
  68.392 +float SPKCONST;
  68.393 +float SOUNDCONST;
  68.394 +float CASCONST;
  68.395 +float GUSCONST,GUSCONST2;
  68.396 +float CGACONST;
  68.397 +float MDACONST;
  68.398 +float VGACONST1,VGACONST2;
  68.399 +float RTCCONST;
  68.400 +int gated,speakval,speakon;
  68.401 +
  68.402 +#define SOUNDBUFLEN (48000/10)
  68.403 +
  68.404 +
  68.405 +/*Sound Blaster*/
  68.406 +int sbenable,sblatchi,sblatcho,sbcount,sb_enable_i,sb_count_i;
  68.407 +int16_t sbdat;
  68.408 +void setsbclock(float clock);
  68.409 +
  68.410 +#define SADLIB 1 /*No DSP*/
  68.411 +#define SB1    2 /*DSP v1.05*/
  68.412 +#define SB15   3 /*DSP v2.00*/
  68.413 +#define SB2    4 /*DSP v2.01 - needed for high-speed DMA*/
  68.414 +#define SBPRO  5 /*DSP v3.00*/
  68.415 +#define SBPRO2 6 /*DSP v3.02 + OPL3*/
  68.416 +#define SB16   7 /*DSP v4.05 + OPL3*/
  68.417 +int sbtype;
  68.418 +
  68.419 +struct
  68.420 +{
  68.421 +        int vocl,vocr,voc;
  68.422 +        int midl,midr,mid;
  68.423 +        int masl,masr,mas;
  68.424 +} sbpmixer;
  68.425 +extern int sb_freq;
  68.426 +
  68.427 +struct
  68.428 +{
  68.429 +        int master_l,master_r;
  68.430 +        int voice_l,voice_r;
  68.431 +        int fm_l,fm_r;
  68.432 +        int bass_l,bass_r;
  68.433 +        int treble_l,treble_r;
  68.434 +        int filter;
  68.435 +} mixer;
  68.436 +
  68.437 +
  68.438 +int clocks[3][12][4];
  68.439 +int at70hz;
  68.440 +
  68.441 +char pcempath[512];
  68.442 +
  68.443 +
  68.444 +/*Hard disc*/
  68.445 +
  68.446 +typedef struct
  68.447 +{
  68.448 +        FILE *f;
  68.449 +        int spt,hpc; /*Sectors per track, heads per cylinder*/
  68.450 +        int tracks;
  68.451 +} PcemHDC;
  68.452 +
  68.453 +PcemHDC hdc[2];
  68.454 +
  68.455 +/*Keyboard*/
  68.456 +int keybsenddelay;
  68.457 +extern int kb_win;
  68.458 +
  68.459 +
  68.460 +/*CD-ROM*/
  68.461 +extern int cdrom_drive;
  68.462 +extern int idecallback[2];
  68.463 +extern int cdrom_enabled;
  68.464 +
  68.465 +void pclog(const char *format, ...);
  68.466 +extern int nmi;
  68.467 +
  68.468 +extern int times;
  68.469 +
  68.470 +
  68.471 +extern float isa_timing, bus_timing;
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/src/ide.c	Sun Apr 21 14:54:35 2013 +0100
    69.3 @@ -0,0 +1,1757 @@
    69.4 +/*RPCemu v0.6 by Tom Walker
    69.5 +  IDE emulation*/
    69.6 +//#define RPCEMU_IDE
    69.7 +
    69.8 +#define IDE_TIME 5
    69.9 +
   69.10 +#define _LARGEFILE_SOURCE
   69.11 +#define _LARGEFILE64_SOURCE
   69.12 +#define _GNU_SOURCE
   69.13 +#include <errno.h>
   69.14 +#include <stdio.h>
   69.15 +#include <stdint.h>
   69.16 +#include <string.h>
   69.17 +
   69.18 +#include <sys/types.h>
   69.19 +
   69.20 +#ifdef RPCEMU_IDE
   69.21 +        #include "rpcemu.h"
   69.22 +        #include "iomd.h"
   69.23 +        #include "arm.h"
   69.24 +#else
   69.25 +        #include "ibm.h"
   69.26 +#endif
   69.27 +#include "ide.h"
   69.28 +
   69.29 +/* Bits of 'atastat' */
   69.30 +#define ERR_STAT		0x01
   69.31 +#define DRQ_STAT		0x08 /* Data request */
   69.32 +#define DSC_STAT                0x10
   69.33 +#define SERVICE_STAT            0x10
   69.34 +#define READY_STAT		0x40
   69.35 +#define BUSY_STAT		0x80
   69.36 +
   69.37 +/* Bits of 'error' */
   69.38 +#define ABRT_ERR		0x04 /* Command aborted */
   69.39 +#define MCR_ERR			0x08 /* Media change request */
   69.40 +
   69.41 +/* ATA Commands */
   69.42 +#define WIN_SRST			0x08 /* ATAPI Device Reset */
   69.43 +#define WIN_RECAL			0x10
   69.44 +#define WIN_RESTORE			WIN_RECAL
   69.45 +#define WIN_READ			0x20 /* 28-Bit Read */
   69.46 +#define WIN_READ_NORETRY                0x21 /* 28-Bit Read - no retry*/
   69.47 +#define WIN_WRITE			0x30 /* 28-Bit Write */
   69.48 +#define WIN_WRITE_NORETRY		0x31 /* 28-Bit Write */
   69.49 +#define WIN_VERIFY			0x40 /* 28-Bit Verify */
   69.50 +#define WIN_FORMAT			0x50
   69.51 +#define WIN_SEEK			0x70
   69.52 +#define WIN_DRIVE_DIAGNOSTICS           0x90 /* Execute Drive Diagnostics */
   69.53 +#define WIN_SPECIFY			0x91 /* Initialize Drive Parameters */
   69.54 +#define WIN_PACKETCMD			0xA0 /* Send a packet command. */
   69.55 +#define WIN_PIDENTIFY			0xA1 /* Identify ATAPI device */
   69.56 +#define WIN_SETIDLE1			0xE3
   69.57 +#define WIN_IDENTIFY			0xEC /* Ask drive to identify itself */
   69.58 +
   69.59 +/* ATAPI Commands */
   69.60 +#define GPCMD_INQUIRY			0x12
   69.61 +#define GPCMD_MODE_SELECT_10		0x55
   69.62 +#define GPCMD_MODE_SENSE_10		0x5a
   69.63 +#define GPCMD_PAUSE_RESUME		0x4b
   69.64 +#define GPCMD_PLAY_AUDIO_12		0xa5
   69.65 +#define GPCMD_PLAY_AUDIO_MSF	        0x47
   69.66 +#define GPCMD_PREVENT_REMOVAL           0x1e
   69.67 +#define GPCMD_READ_10                   0x28
   69.68 +#define GPCMD_READ_CD			0xbe
   69.69 +#define GPCMD_READ_HEADER		0x44
   69.70 +#define GPCMD_READ_SUBCHANNEL		0x42
   69.71 +#define GPCMD_READ_TOC_PMA_ATIP		0x43
   69.72 +#define GPCMD_REQUEST_SENSE		0x03
   69.73 +#define GPCMD_SEEK			0x2b
   69.74 +#define GPCMD_SEND_DVD_STRUCTURE	0xad
   69.75 +#define GPCMD_SET_SPEED			0xbb
   69.76 +#define GPCMD_START_STOP_UNIT		0x1b
   69.77 +#define GPCMD_TEST_UNIT_READY		0x00
   69.78 +
   69.79 +/* Mode page codes for mode sense/set */
   69.80 +#define GPMODE_R_W_ERROR_PAGE		0x01
   69.81 +#define GPMODE_CDROM_PAGE		0x0d
   69.82 +#define GPMODE_CDROM_AUDIO_PAGE		0x0e
   69.83 +#define GPMODE_CAPABILITIES_PAGE	0x2a
   69.84 +#define GPMODE_ALL_PAGES		0x3f
   69.85 +
   69.86 +/* ATAPI Sense Keys */
   69.87 +#define SENSE_NONE		0
   69.88 +#define SENSE_NOT_READY		2
   69.89 +#define SENSE_ILLEGAL_REQUEST	5
   69.90 +#define SENSE_UNIT_ATTENTION	6
   69.91 +
   69.92 +/* ATAPI Additional Sense Codes */
   69.93 +#define ASC_ILLEGAL_OPCODE		0x20
   69.94 +#define ASC_MEDIUM_NOT_PRESENT		0x3a
   69.95 +
   69.96 +/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw).
   69.97 +   Not that it means anything */
   69.98 +#define CDROM_SPEED	706
   69.99 +
  69.100 +/** Evaluate to non-zero if the currently selected drive is an ATAPI device */
  69.101 +#define IDE_DRIVE_IS_CDROM(ide)  (ide->type == IDE_CDROM)
  69.102 +/*
  69.103 +\
  69.104 +	(!ide.drive)*/
  69.105 +
  69.106 +ATAPI *atapi;
  69.107 +
  69.108 +enum
  69.109 +{
  69.110 +        IDE_NONE = 0,
  69.111 +        IDE_HDD,
  69.112 +        IDE_CDROM
  69.113 +};
  69.114 +
  69.115 +typedef struct IDE
  69.116 +{
  69.117 +        int type;
  69.118 +        int board;
  69.119 +        uint8_t atastat;
  69.120 +        uint8_t error;
  69.121 +        int secount,sector,cylinder,head,drive,cylprecomp;
  69.122 +        uint8_t command;
  69.123 +        uint8_t fdisk;
  69.124 +        int pos;
  69.125 +        int packlen;
  69.126 +        int spt,hpc;
  69.127 +        int tracks;
  69.128 +        int packetstatus;
  69.129 +        int cdpos,cdlen;
  69.130 +        uint8_t asc;
  69.131 +        int discchanged;
  69.132 +        int reset;
  69.133 +        FILE *hdfile;
  69.134 +        uint16_t buffer[65536];
  69.135 +        int irqstat;
  69.136 +        int service;
  69.137 +        int lba;
  69.138 +        uint32_t lba_addr;
  69.139 +        int skip512;
  69.140 +} IDE;
  69.141 +
  69.142 +IDE ide_drives[4];
  69.143 +
  69.144 +IDE *ext_ide;
  69.145 +
  69.146 +char ide_fn[2][512];
  69.147 +
  69.148 +static void callreadcd(IDE *ide);
  69.149 +static void atapicommand(int ide_board);
  69.150 +
  69.151 +int idecallback[2] = {0, 0};
  69.152 +
  69.153 +int cur_ide[2];
  69.154 +
  69.155 +uint8_t getstat(IDE *ide) { return ide->atastat; }
  69.156 +
  69.157 +static inline void ide_irq_raise(IDE *ide)
  69.158 +{
  69.159 +//        pclog("IDE_IRQ_RAISE\n");
  69.160 +	if (!(ide->fdisk&2)) {
  69.161 +#ifdef RPCEMU_IDE
  69.162 +		iomd.irqb.status |= IOMD_IRQB_IDE;
  69.163 +		updateirqs();
  69.164 +#else
  69.165 +//                if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n");
  69.166 +                picint((ide->board)?(1<<15):(1<<14));
  69.167 +#endif
  69.168 +	}
  69.169 +	ide->irqstat=1;
  69.170 +        ide->service=1;
  69.171 +}
  69.172 +
  69.173 +static inline void ide_irq_lower(IDE *ide)
  69.174 +{
  69.175 +//        pclog("IDE_IRQ_LOWER\n");
  69.176 +//	if (ide.board == 0) {
  69.177 +#ifdef RPCEMU_IDE
  69.178 +		iomd.irqb.status &= ~IOMD_IRQB_IDE;
  69.179 +		updateirqs();
  69.180 +#else
  69.181 +                picintc((ide->board)?(1<<15):(1<<14));
  69.182 +#endif
  69.183 +//	}
  69.184 +	ide->irqstat=0;
  69.185 +}
  69.186 +
  69.187 +void ide_irq_update(IDE *ide)
  69.188 +{
  69.189 +#ifdef RPCEMU_IDE
  69.190 +	if (ide->irqstat && !(iomd.irqb.status & IOMD_IRQB_IDE) && !(ide->fdisk & 2)) {
  69.191 +		iomd.irqb.status |= IOMD_IRQB_IDE;
  69.192 +		updateirqs();
  69.193 +        }
  69.194 +        else if (iomd.irqb.status & IOMD_IRQB_IDE)
  69.195 +        {
  69.196 +		iomd.irqb.status &= ~IOMD_IRQB_IDE;
  69.197 +		updateirqs();
  69.198 +        }
  69.199 +#else
  69.200 +	if (ide->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(ide->fdisk & 2))
  69.201 +            picint((ide->board)?(1<<15):(1<<14));
  69.202 +        else if ((pic2.pend|pic2.ins)&0x40)
  69.203 +            picintc((ide->board)?(1<<15):(1<<14));
  69.204 +#endif
  69.205 +}
  69.206 +/**
  69.207 + * Copy a string into a buffer, padding with spaces, and placing characters as
  69.208 + * if they were packed into 16-bit values, stored little-endian.
  69.209 + *
  69.210 + * @param str Destination buffer
  69.211 + * @param src Source string
  69.212 + * @param len Length of destination buffer to fill in. Strings shorter than
  69.213 + *            this length will be padded with spaces.
  69.214 + */
  69.215 +static void
  69.216 +ide_padstr(char *str, const char *src, int len)
  69.217 +{
  69.218 +	int i, v;
  69.219 +
  69.220 +	for (i = 0; i < len; i++) {
  69.221 +		if (*src != '\0') {
  69.222 +			v = *src++;
  69.223 +		} else {
  69.224 +			v = ' ';
  69.225 +		}
  69.226 +		str[i ^ 1] = v;
  69.227 +	}
  69.228 +}
  69.229 +
  69.230 +/**
  69.231 + * Copy a string into a buffer, padding with spaces. Does not add string
  69.232 + * terminator.
  69.233 + *
  69.234 + * @param buf      Destination buffer
  69.235 + * @param buf_size Size of destination buffer to fill in. Strings shorter than
  69.236 + *                 this length will be padded with spaces.
  69.237 + * @param src      Source string
  69.238 + */
  69.239 +static void
  69.240 +ide_padstr8(uint8_t *buf, int buf_size, const char *src)
  69.241 +{
  69.242 +	int i;
  69.243 +
  69.244 +	for (i = 0; i < buf_size; i++) {
  69.245 +		if (*src != '\0') {
  69.246 +			buf[i] = *src++;
  69.247 +		} else {
  69.248 +			buf[i] = ' ';
  69.249 +		}
  69.250 +	}
  69.251 +}
  69.252 +
  69.253 +/**
  69.254 + * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command
  69.255 + */
  69.256 +static void ide_identify(IDE *ide)
  69.257 +{
  69.258 +	memset(ide->buffer, 0, 512);
  69.259 +
  69.260 +	//ide->buffer[1] = 101; /* Cylinders */
  69.261 +
  69.262 +#ifdef RPCEMU_IDE
  69.263 +	ide->buffer[1] = 65535; /* Cylinders */
  69.264 +	ide->buffer[3] = 16;  /* Heads */
  69.265 +	ide->buffer[6] = 63;  /* Sectors */
  69.266 +#else
  69.267 +	ide->buffer[1] = hdc[cur_ide[0]].tracks; /* Cylinders */
  69.268 +	ide->buffer[3] = hdc[cur_ide[0]].hpc;  /* Heads */
  69.269 +	ide->buffer[6] = hdc[cur_ide[0]].spt;  /* Sectors */
  69.270 +#endif
  69.271 +	ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
  69.272 +	ide_padstr((char *) (ide->buffer + 23), "v1.0", 8); /* Firmware */
  69.273 +#ifdef RPCEMU_IDE
  69.274 +	ide_padstr((char *) (ide->buffer + 27), "RPCemuHD", 40); /* Model */
  69.275 +#else
  69.276 +	ide_padstr((char *) (ide->buffer + 27), "PCemHD", 40); /* Model */
  69.277 +#endif
  69.278 +	ide->buffer[49] = (1<<9); /* LBA supported */
  69.279 +	ide->buffer[50] = 0x4000; /* Capabilities */
  69.280 +#ifdef RPCEMU_IDE
  69.281 +	ide->buffer[60] = (65535 * 16 * 63) & 0xFFFF; /* Total addressable sectors (LBA) */
  69.282 +	ide->buffer[61] = (65535 * 16 * 63) >> 16;
  69.283 +#else
  69.284 +	ide->buffer[60] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */
  69.285 +	ide->buffer[61] = (hdc[cur_ide[0]].tracks * hdc[cur_ide[0]].hpc * hdc[cur_ide[0]].spt) >> 16;
  69.286 +#endif
  69.287 +}
  69.288 +
  69.289 +/**
  69.290 + * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command
  69.291 + */
  69.292 +static void ide_atapi_identify(IDE *ide)
  69.293 +{
  69.294 +	memset(ide->buffer, 0, 512);
  69.295 +
  69.296 +	ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */
  69.297 +	ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
  69.298 +	ide_padstr((char *) (ide->buffer + 23), "v1.0", 8); /* Firmware */
  69.299 +#ifdef RPCEMU_IDE
  69.300 +	ide_padstr((char *) (ide->buffer + 27), "RPCemuCD", 40); /* Model */
  69.301 +#else
  69.302 +	ide_padstr((char *) (ide->buffer + 27), "PCemCD", 40); /* Model */
  69.303 +#endif
  69.304 +	ide->buffer[49] = 0x200; /* LBA supported */
  69.305 +}
  69.306 +
  69.307 +/**
  69.308 + * Fill in ide->buffer with the output of the ATAPI "MODE SENSE" command
  69.309 + *
  69.310 + * @param pos Offset within the buffer to start filling in data
  69.311 + *
  69.312 + * @return Offset within the buffer after the end of the data
  69.313 + */
  69.314 +static uint32_t ide_atapi_mode_sense(IDE *ide, uint32_t pos, uint8_t type)
  69.315 +{
  69.316 +	uint8_t *buf = (uint8_t *) ide->buffer;
  69.317 +//        pclog("ide_atapi_mode_sense %02X\n",type);
  69.318 +        if (type==GPMODE_ALL_PAGES || type==GPMODE_R_W_ERROR_PAGE)
  69.319 +        {
  69.320 +        	/* &01 - Read error recovery */
  69.321 +        	buf[pos++] = GPMODE_R_W_ERROR_PAGE;
  69.322 +        	buf[pos++] = 6; /* Page length */
  69.323 +        	buf[pos++] = 0; /* Error recovery parameters */
  69.324 +        	buf[pos++] = 3; /* Read retry count */
  69.325 +        	buf[pos++] = 0; /* Reserved */
  69.326 +        	buf[pos++] = 0; /* Reserved */
  69.327 +        	buf[pos++] = 0; /* Reserved */
  69.328 +        	buf[pos++] = 0; /* Reserved */
  69.329 +        }
  69.330 +
  69.331 +        if (type==GPMODE_ALL_PAGES || type==GPMODE_CDROM_PAGE)
  69.332 +        {
  69.333 +        	/* &0D - CD-ROM Parameters */
  69.334 +        	buf[pos++] = GPMODE_CDROM_PAGE;
  69.335 +        	buf[pos++] = 6; /* Page length */
  69.336 +        	buf[pos++] = 0; /* Reserved */
  69.337 +        	buf[pos++] = 1; /* Inactivity time multiplier *NEEDED BY RISCOS* value is a guess */
  69.338 +        	buf[pos++] = 0; buf[pos++] = 60; /* MSF settings */
  69.339 +        	buf[pos++] = 0; buf[pos++] = 75; /* MSF settings */
  69.340 +        }
  69.341 +
  69.342 +        if (type==GPMODE_ALL_PAGES || type==GPMODE_CDROM_AUDIO_PAGE)
  69.343 +        {
  69.344 +        	/* &0e - CD-ROM Audio Control Parameters */
  69.345 +        	buf[pos++] = GPMODE_CDROM_AUDIO_PAGE;
  69.346 +        	buf[pos++] = 0xE; /* Page length */
  69.347 +        	buf[pos++] = 4; /* Reserved */
  69.348 +        	buf[pos++] = 0; /* Reserved */
  69.349 +        	buf[pos++] = 0; /* Reserved */
  69.350 +        	buf[pos++] = 0; /* Reserved */
  69.351 +        	buf[pos++] = 0; buf[pos++] = 75; /* Logical audio block per second */
  69.352 +        	buf[pos++] = 1;    /* CDDA Output Port 0 Channel Selection */
  69.353 +        	buf[pos++] = 0xFF; /* CDDA Output Port 0 Volume */
  69.354 +        	buf[pos++] = 2;    /* CDDA Output Port 1 Channel Selection */
  69.355 +        	buf[pos++] = 0xFF; /* CDDA Output Port 1 Volume */
  69.356 +        	buf[pos++] = 0;    /* CDDA Output Port 2 Channel Selection */
  69.357 +        	buf[pos++] = 0;    /* CDDA Output Port 2 Volume */
  69.358 +        	buf[pos++] = 0;    /* CDDA Output Port 3 Channel Selection */
  69.359 +        	buf[pos++] = 0;    /* CDDA Output Port 3 Volume */
  69.360 +        }
  69.361 +
  69.362 +        if (type==GPMODE_ALL_PAGES || type==GPMODE_CAPABILITIES_PAGE)
  69.363 +        {
  69.364 +//                pclog("Capabilities page\n");
  69.365 +               	/* &2A - CD-ROM capabilities and mechanical status */
  69.366 +        	buf[pos++] = GPMODE_CAPABILITIES_PAGE;
  69.367 +        	buf[pos++] = 0x12; /* Page length */
  69.368 +        	buf[pos++] = 0; buf[pos++] = 0; /* CD-R methods */
  69.369 +        	buf[pos++] = 1; /* Supports audio play, not multisession */
  69.370 +        	buf[pos++] = 0; /* Some other stuff not supported */
  69.371 +        	buf[pos++] = 0; /* Some other stuff not supported (lock state + eject) */
  69.372 +        	buf[pos++] = 0; /* Some other stuff not supported */
  69.373 +        	buf[pos++] = (uint8_t) (CDROM_SPEED >> 8);
  69.374 +        	buf[pos++] = (uint8_t) CDROM_SPEED; /* Maximum speed */
  69.375 +        	buf[pos++] = 0; buf[pos++] = 2; /* Number of audio levels - on and off only */
  69.376 +        	buf[pos++] = 0; buf[pos++] = 0; /* Buffer size - none */
  69.377 +        	buf[pos++] = (uint8_t) (CDROM_SPEED >> 8);
  69.378 +        	buf[pos++] = (uint8_t) CDROM_SPEED; /* Current speed */
  69.379 +        	buf[pos++] = 0; /* Reserved */
  69.380 +        	buf[pos++] = 0; /* Drive digital format */
  69.381 +        	buf[pos++] = 0; /* Reserved */
  69.382 +        	buf[pos++] = 0; /* Reserved */
  69.383 +        }
  69.384 +
  69.385 +	return pos;
  69.386 +}
  69.387 +
  69.388 +/*
  69.389 + * Return the sector offset for the current register values
  69.390 + */
  69.391 +static off64_t ide_get_sector(IDE *ide)
  69.392 +{
  69.393 +        if (ide->lba)
  69.394 +        {
  69.395 +                return (off64_t)ide->lba_addr + ide->skip512;
  69.396 +        }
  69.397 +        else
  69.398 +        {
  69.399 +        	int heads = ide->hpc;
  69.400 +        	int sectors = ide->spt;
  69.401 +
  69.402 +        	return ((((off64_t) ide->cylinder * heads) + ide->head) *
  69.403 +        	          sectors) + (ide->sector - 1) + ide->skip512;
  69.404 +        }
  69.405 +}
  69.406 +
  69.407 +/**
  69.408 + * Move to the next sector using CHS addressing
  69.409 + */
  69.410 +static void ide_next_sector(IDE *ide)
  69.411 +{
  69.412 +        if (ide->lba)
  69.413 +        {
  69.414 +                ide->lba_addr++;
  69.415 +        }
  69.416 +        else
  69.417 +        {
  69.418 +        	ide->sector++;
  69.419 +        	if (ide->sector == (ide->spt + 1)) {
  69.420 +        		ide->sector = 1;
  69.421 +        		ide->head++;
  69.422 +        		if (ide->head == ide->hpc) {
  69.423 +        			ide->head = 0;
  69.424 +        			ide->cylinder++;
  69.425 +                        }
  69.426 +		}
  69.427 +	}
  69.428 +}
  69.429 +
  69.430 +#ifdef RPCEMU_IDE
  69.431 +static void loadhd(IDE *ide, int d, const char *fn)
  69.432 +{
  69.433 +	char pathname[512];
  69.434 +
  69.435 +	append_filename(pathname, rpcemu_get_datadir(), fn, 512);
  69.436 +
  69.437 +        rpclog("Loading %s\n",pathname);
  69.438 +	if (ide->hdfile == NULL) {
  69.439 +		/* Try to open existing hard disk image */
  69.440 +		ide->hdfile = fopen64(pathname, "rb+");
  69.441 +		if (ide->hdfile == NULL) {
  69.442 +			/* Failed to open existing hard disk image */
  69.443 +			if (errno == ENOENT) {
  69.444 +				/* Failed because it does not exist,
  69.445 +				   so try to create new file */
  69.446 +				ide->hdfile = fopen64(pathname, "wb+");
  69.447 +				if (ide->hdfile == NULL) {
  69.448 +					fatal("Cannot create file '%s': %s",
  69.449 +					      pathname, strerror(errno));
  69.450 +				}
  69.451 +			} else {
  69.452 +				/* Failed for another reason */
  69.453 +				fatal("Cannot open file '%s': %s",
  69.454 +				      pathname, strerror(errno));
  69.455 +			}
  69.456 +		}
  69.457 +	}
  69.458 +
  69.459 +        fseek(ide->hdfile, 0xfc1, SEEK_SET);
  69.460 +        ide->spt = getc(ide->hdfile);
  69.461 +        ide->hpc = getc(ide->hdfile);
  69.462 +        ide->skip512 = 1;
  69.463 +//        rpclog("First check - spt %i hpc %i\n",ide.spt[0],ide.hpc[0]);
  69.464 +        if (!ide->spt || !ide->hpc)
  69.465 +        {
  69.466 +                fseek(ide->hdfile, 0xdc1, SEEK_SET);
  69.467 +                ide->spt = getc(ide->hdfile);
  69.468 +                ide->hpc = getc(ide->hdfile);
  69.469 +//                rpclog("Second check - spt %i hpc %i\n",ide.spt[0],ide.hpc[0]);
  69.470 +                ide->skip512 = 0;
  69.471 +                if (!ide->spt || !ide->hpc)
  69.472 +                {
  69.473 +                        ide->spt=63;
  69.474 +                        ide->hpc=16;
  69.475 +                        ide->skip512 = 1;
  69.476 +//        rpclog("Final check - spt %i hpc %i\n",ide.spt[0],ide.hpc[0]);
  69.477 +                }
  69.478 +        }
  69.479 +
  69.480 +        ide->type = IDE_HDD;
  69.481 +        
  69.482 +        rpclog("%i %i %i\n",ide->spt,ide->hpc,ide->skip512);
  69.483 +}
  69.484 +#else
  69.485 +static void loadhd(IDE *ide, int d, const char *fn)
  69.486 +{
  69.487 +	if (ide->hdfile == NULL) {
  69.488 +		/* Try to open existing hard disk image */
  69.489 +		ide->hdfile = fopen64(fn, "rb+");
  69.490 +		if (ide->hdfile == NULL) {
  69.491 +			/* Failed to open existing hard disk image */
  69.492 +			if (errno == ENOENT) {
  69.493 +				/* Failed because it does not exist,
  69.494 +				   so try to create new file */
  69.495 +				ide->hdfile = fopen64(fn, "wb+");
  69.496 +				if (ide->hdfile == NULL) {
  69.497 +                                        ide->type = IDE_NONE;
  69.498 +/*					fatal("Cannot create file '%s': %s",
  69.499 +					      fn, strerror(errno));*/
  69.500 +				}
  69.501 +			} else {
  69.502 +				/* Failed for another reason */
  69.503 +                                ide->type = IDE_NONE;
  69.504 +/*				fatal("Cannot open file '%s': %s",
  69.505 +				      fn, strerror(errno));*/
  69.506 +			}
  69.507 +		}
  69.508 +	}
  69.509 +
  69.510 +        ide->spt = hdc[d].spt;
  69.511 +        ide->hpc = hdc[d].hpc;
  69.512 +        ide->tracks = hdc[d].tracks;
  69.513 +        ide->type = IDE_HDD;
  69.514 +}
  69.515 +#endif
  69.516 +
  69.517 +void resetide(void)
  69.518 +{
  69.519 +        int d;
  69.520 +
  69.521 +        /* Close hard disk image files (if previously open) */
  69.522 +        for (d = 0; d < 4; d++) {
  69.523 +                ide_drives[d].type = IDE_NONE;
  69.524 +                if (ide_drives[d].hdfile != NULL) {
  69.525 +                        fclose(ide_drives[d].hdfile);
  69.526 +                        ide_drives[d].hdfile = NULL;
  69.527 +                }
  69.528 +                ide_drives[d].atastat = READY_STAT | DSC_STAT;
  69.529 +                ide_drives[d].service = 0;
  69.530 +                ide_drives[d].board = (d & 2) ? 1 : 0;
  69.531 +        }
  69.532 +
  69.533 +        idecallback[0]=idecallback[1]=0;
  69.534 +#ifdef RPCEMU_IDE
  69.535 +	loadhd(&ide_drives[0], 0, "hd4.hdf");
  69.536 +	if (!config.cdromenabled) {
  69.537 +		loadhd(&ide_drives[1], 1, "hd5.hdf");
  69.538 +	}
  69.539 +	else
  69.540 +           ide_drives[1].type = IDE_CDROM;
  69.541 +#else
  69.542 +        loadhd(&ide_drives[0], 0, ide_fn[0]);
  69.543 +        loadhd(&ide_drives[1], 1, ide_fn[1]);
  69.544 +        if (cdrom_enabled)
  69.545 +           ide_drives[2].type = IDE_CDROM;
  69.546 +#endif
  69.547 +
  69.548 +        cur_ide[0] = 0;
  69.549 +        cur_ide[1] = 2;
  69.550 +        
  69.551 +//        ide_drives[1].type = IDE_CDROM;
  69.552 +}
  69.553 +
  69.554 +int idetimes=0;
  69.555 +void writeidew(int ide_board, uint16_t val)
  69.556 +{
  69.557 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
  69.558 +#ifndef RPCEMU_IDE
  69.559 +/*        if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
  69.560 +        {
  69.561 +//                pclog("Failed write IDE %04X:%08X\n",CS,pc);
  69.562 +                return;
  69.563 +        }*/
  69.564 +#endif
  69.565 +#ifdef _RPCEMU_BIG_ENDIAN
  69.566 +		val=(val>>8)|(val<<8);
  69.567 +#endif
  69.568 +//        pclog("Write IDEw %04X\n",val);
  69.569 +        ide->buffer[ide->pos >> 1] = val;
  69.570 +        ide->pos+=2;
  69.571 +
  69.572 +        if (ide->packetstatus==4)
  69.573 +        {
  69.574 +                if (ide->pos>=(ide->packlen+2))
  69.575 +                {
  69.576 +                        ide->packetstatus=5;
  69.577 +                        idecallback[ide_board]=6*IDE_TIME;
  69.578 +//                        pclog("Packet over!\n");
  69.579 +                        ide_irq_lower(ide);
  69.580 +                }
  69.581 +                return;
  69.582 +        }
  69.583 +        else if (ide->packetstatus==5) return;
  69.584 +        else if (ide->command == WIN_PACKETCMD && ide->pos>=0xC)
  69.585 +        {
  69.586 +                ide->pos=0;
  69.587 +                ide->atastat = BUSY_STAT;
  69.588 +                ide->packetstatus=1;
  69.589 +                idecallback[ide_board]=6*IDE_TIME;
  69.590 +                callbackide(ide_board);
  69.591 +//                idecallback[ide_board]=60*IDE_TIME;
  69.592 +//                if ((ide->buffer[0]&0xFF)==0x43) idecallback[ide_board]=1*IDE_TIME;
  69.593 +//                pclog("Packet now waiting!\n");
  69.594 +/*                if (ide->buffer[0]==0x243)
  69.595 +                {
  69.596 +                        idetimes++;
  69.597 +                        output=3;
  69.598 +                }*/
  69.599 +        }
  69.600 +        else if (ide->pos>=512)
  69.601 +        {
  69.602 +                ide->pos=0;
  69.603 +                ide->atastat = BUSY_STAT;
  69.604 +                idecallback[ide_board]=6*IDE_TIME;
  69.605 +//                callbackide(ide_board);
  69.606 +        }
  69.607 +}
  69.608 +
  69.609 +void writeide(int ide_board, uint16_t addr, uint8_t val)
  69.610 +{
  69.611 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
  69.612 +        uint8_t *idebufferb = (uint8_t *) ide->buffer;
  69.613 +#ifndef RPCEMU_IDE
  69.614 +/*        if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
  69.615 +        {
  69.616 +//                pclog("Failed write IDE %04X:%08X\n",CS,pc);
  69.617 +                return;
  69.618 +        }*/
  69.619 +#endif
  69.620 +//        return;
  69.621 +        addr|=0x80;
  69.622 +//        if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i  %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat);
  69.623 +        /*if (idedebug) */
  69.624 +//        pclog("Write IDE %08X %02X %04X:%08X\n",addr,val,CS,pc);
  69.625 +//        int c;
  69.626 +//      rpclog("Write IDE %08X %02X %08X %08X\n",addr,val,PC,armregs[12]);
  69.627 +
  69.628 +        if (ide->type == IDE_NONE && addr != 0x1f6) return;
  69.629 +        
  69.630 +        switch (addr)
  69.631 +        {
  69.632 +        case 0x1F0: /* Data */
  69.633 +                writeidew(ide_board, val | (val << 8));
  69.634 +                return;
  69.635 +
  69.636 +        case 0x1F1: /* Features */
  69.637 +                ide->cylprecomp=val;
  69.638 +                return;
  69.639 +
  69.640 +        case 0x1F2: /* Sector count */
  69.641 +                ide->secount=val;
  69.642 +                return;
  69.643 +
  69.644 +        case 0x1F3: /* Sector */
  69.645 +                ide->sector=val;
  69.646 +                ide->lba_addr=(ide->lba_addr&0xFFFFF00)|val;
  69.647 +                return;
  69.648 +
  69.649 +        case 0x1F4: /* Cylinder low */
  69.650 +                ide->cylinder=(ide->cylinder&0xFF00)|val;
  69.651 +                ide->lba_addr=(ide->lba_addr&0xFFF00FF)|(val<<8);
  69.652 +//                pclog("Write cylinder low %02X\n",val);
  69.653 +                return;
  69.654 +
  69.655 +        case 0x1F5: /* Cylinder high */
  69.656 +                ide->cylinder=(ide->cylinder&0xFF)|(val<<8);
  69.657 +                ide->lba_addr=(ide->lba_addr&0xF00FFFF)|(val<<16);
  69.658 +                return;
  69.659 +
  69.660 +        case 0x1F6: /* Drive/Head */
  69.661 +/*        if (val==0xB0)
  69.662 +        {
  69.663 +                dumpregs();
  69.664 +                exit(-1);
  69.665 +        }*/
  69.666 +                cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1);
  69.667 +                ide = &ide_drives[cur_ide[ide_board]];
  69.668 +                
  69.669 +                ide->head=val&0xF;
  69.670 +                ide->lba=val&0x40;
  69.671 +                
  69.672 +                ide->lba_addr=(ide->lba_addr&0x0FFFFFF)|((val&0xF)<<24);
  69.673 +                
  69.674 +                ide_irq_update(ide);
  69.675 +                return;
  69.676 +
  69.677 +        case 0x1F7: /* Command register */
  69.678 +        if (ide->type == IDE_NONE) return;
  69.679 +//                pclog("IDE command %02X drive %i\n",val,ide.drive);
  69.680 +        ide_irq_lower(ide);
  69.681 +                ide->command=val;
  69.682 +                
  69.683 +//                pclog("New IDE command - %02X %i %i\n",ide->command,cur_ide[ide_board],ide_board);
  69.684 +                ide->error=0;
  69.685 +                switch (val)
  69.686 +                {
  69.687 +                case WIN_SRST: /* ATAPI Device Reset */
  69.688 +                        if (IDE_DRIVE_IS_CDROM(ide)) ide->atastat = BUSY_STAT;
  69.689 +                        else                         ide->atastat = READY_STAT;
  69.690 +                        idecallback[ide_board]=100*IDE_TIME;
  69.691 +                        return;
  69.692 +
  69.693 +                case WIN_RESTORE:
  69.694 +                case WIN_SEEK:
  69.695 +                        ide->atastat = READY_STAT;
  69.696 +                        idecallback[ide_board]=100*IDE_TIME;
  69.697 +                        return;
  69.698 +
  69.699 +                case WIN_READ:
  69.700 +                case WIN_READ_NORETRY:
  69.701 +/*                        if (ide.secount>1)
  69.702 +                        {
  69.703 +                                fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
  69.704 +                        }*/
  69.705 +#if 0
  69.706 +                        if (ide->lba) pclog("Read %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
  69.707 +                        else          pclog("Read %i sectors from sector %i cylinder %i head %i  %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins);
  69.708 +#endif
  69.709 +                        ide->atastat = BUSY_STAT;
  69.710 +                        idecallback[ide_board]=200*IDE_TIME;
  69.711 +                        return;
  69.712 +
  69.713 +                case WIN_WRITE:
  69.714 +                case WIN_WRITE_NORETRY:                        
  69.715 +/*                        if (ide.secount>1)
  69.716 +                        {
  69.717 +                                fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head);
  69.718 +                        }*/
  69.719 +#if 0
  69.720 +                        if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
  69.721 +                        else          pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
  69.722 +#endif
  69.723 +                        ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT;
  69.724 +                        ide->pos=0;
  69.725 +                        return;
  69.726 +
  69.727 +                case WIN_VERIFY:
  69.728 +#if 0
  69.729 +                        if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr);
  69.730 +                        else          pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head);
  69.731 +#endif
  69.732 +                        ide->atastat = BUSY_STAT;
  69.733 +                        idecallback[ide_board]=200*IDE_TIME;
  69.734 +                        return;
  69.735 +
  69.736 +                case WIN_FORMAT:
  69.737 +//                        pclog("Format track %i head %i\n",ide.cylinder,ide.head);
  69.738 +                        ide->atastat = DRQ_STAT;
  69.739 +//                        idecallback[ide_board]=200;
  69.740 +                        ide->pos=0;
  69.741 +                        return;
  69.742 +
  69.743 +                case WIN_SPECIFY: /* Initialize Drive Parameters */
  69.744 +                        ide->atastat = BUSY_STAT;
  69.745 +                        idecallback[ide_board]=200*IDE_TIME;
  69.746 +//                        pclog("SPECIFY\n");
  69.747 +//                        output=1;
  69.748 +                        return;
  69.749 +
  69.750 +                case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */
  69.751 +                case WIN_PIDENTIFY: /* Identify Packet Device */
  69.752 +//                output=1;
  69.753 +                case WIN_SETIDLE1: /* Idle */
  69.754 +                        ide->atastat = BUSY_STAT;
  69.755 +                        idecallback[ide_board]=200*IDE_TIME;
  69.756 +                        return;
  69.757 +
  69.758 +                case WIN_IDENTIFY: /* Identify Device */
  69.759 +                case 0xEF:
  69.760 +//                        output=3;
  69.761 +//                        timetolive=500;
  69.762 +                        ide->atastat = BUSY_STAT;
  69.763 +                        idecallback[ide_board]=200*IDE_TIME;
  69.764 +                        return;
  69.765 +
  69.766 +                case WIN_PACKETCMD: /* ATAPI Packet */
  69.767 +                        ide->packetstatus=0;
  69.768 +                        ide->atastat = BUSY_STAT;
  69.769 +                        idecallback[ide_board]=1;//30*IDE_TIME;
  69.770 +                        ide->pos=0;
  69.771 +                        return;
  69.772 +                        
  69.773 +                case 0xF0:
  69.774 +                        default:
  69.775 +                	ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
  69.776 +                	ide->error = ABRT_ERR;
  69.777 +                        ide_irq_raise(ide);
  69.778 +                        return;
  69.779 +                }
  69.780 +//                fatal("Bad IDE command %02X\n", val);
  69.781 +                return;
  69.782 +
  69.783 +        case 0x3F6: /* Device control */
  69.784 +                if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE))
  69.785 +                {
  69.786 +                        idecallback[ide_board]=500*IDE_TIME;
  69.787 +                        ide->reset = 1;
  69.788 +                        ide->atastat = BUSY_STAT;
  69.789 +//                        pclog("IDE Reset\n");
  69.790 +                }
  69.791 +                ide->fdisk=val;
  69.792 +                ide_irq_update(ide);
  69.793 +                return;
  69.794 +        }
  69.795 +//        fatal("Bad IDE write %04X %02X\n", addr, val);
  69.796 +}
  69.797 +
  69.798 +uint8_t readide(int ide_board, uint16_t addr)
  69.799 +{
  69.800 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
  69.801 +        const uint8_t *idebufferb = (const uint8_t *) ide->buffer;
  69.802 +        uint8_t temp;
  69.803 +        uint16_t tempw;
  69.804 +
  69.805 +        addr|=0x80;
  69.806 +#ifndef RPCEMU_IDE
  69.807 +/*        if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
  69.808 +        {
  69.809 +//                pclog("Failed read IDE %04X:%08X\n",CS,pc);
  69.810 +                return 0xFF;
  69.811 +        }*/
  69.812 +#endif
  69.813 +//        return 0xFF;
  69.814 +
  69.815 +        if (ide->type == IDE_NONE && addr != 0x1f6) return 0xff;
  69.816 +//        /*if (addr!=0x1F7 && addr!=0x3F6) */pclog("Read IDEb %04X %02X %02X %i %04X:%04X %i  %04X\n",addr,ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board, BX);
  69.817 +//rpclog("Read IDE %08X %08X %02X\n",addr,PC,iomd.irqb.mask);
  69.818 +        switch (addr)
  69.819 +        {
  69.820 +        case 0x1F0: /* Data */
  69.821 +                tempw = readidew(ide_board);
  69.822 +//                pclog("Read IDEW %04X\n", tempw);                
  69.823 +                temp = tempw & 0xff;
  69.824 +                break;
  69.825 +                
  69.826 +        case 0x1F1: /* Error */
  69.827 +//        pclog("Read error %02X\n",ide.error);
  69.828 +                temp = ide->error;
  69.829 +                break;
  69.830 +
  69.831 +        case 0x1F2: /* Sector count */
  69.832 +//        pclog("Read sector count %02X\n",ide->secount);
  69.833 +                temp = (uint8_t)ide->secount;
  69.834 +                break;
  69.835 +
  69.836 +        case 0x1F3: /* Sector */
  69.837 +                temp = (uint8_t)ide->sector;
  69.838 +                break;
  69.839 +
  69.840 +        case 0x1F4: /* Cylinder low */
  69.841 +//        pclog("Read cyl low %02X\n",ide.cylinder&0xFF);
  69.842 +                temp = (uint8_t)(ide->cylinder&0xFF);
  69.843 +                break;
  69.844 +
  69.845 +        case 0x1F5: /* Cylinder high */
  69.846 +//        pclog("Read cyl low %02X\n",ide.cylinder>>8);
  69.847 +                temp = (uint8_t)(ide->cylinder>>8);
  69.848 +                break;
  69.849 +
  69.850 +        case 0x1F6: /* Drive/Head */
  69.851 +                temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0);
  69.852 +                break;
  69.853 +
  69.854 +        case 0x1F7: /* Status */
  69.855 +                if (ide->type == IDE_NONE)
  69.856 +                {
  69.857 +//                        pclog("Return status 00\n");
  69.858 +                        temp = 0;
  69.859 +                        break;
  69.860 +                }
  69.861 +                ide_irq_lower(ide);
  69.862 +                if (ide->fdisk & 4)
  69.863 +                   temp = 0x80;
  69.864 +                else if (ide->type == IDE_CDROM)
  69.865 +                {
  69.866 +//                        pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0));
  69.867 +                        temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
  69.868 +                }
  69.869 +                else
  69.870 +                {
  69.871 +//                 && ide->service) return ide.atastat[ide.board]|SERVICE_STAT;
  69.872 +//                pclog("Return status %02X\n",ide->atastat);
  69.873 +                        temp = ide->atastat;
  69.874 +                }
  69.875 +                break;
  69.876 +
  69.877 +        case 0x3F6: /* Alternate Status */
  69.878 +//        pclog("3F6 read %02X\n",ide.atastat[ide.board]);
  69.879 +//        if (output) output=0;
  69.880 +                if (ide->type == IDE_NONE)
  69.881 +                {
  69.882 +//                        pclog("Return status 00\n");
  69.883 +                        temp = 0;
  69.884 +                        break;
  69.885 +                }
  69.886 +                if (ide->type == IDE_CDROM)
  69.887 +                {
  69.888 +//                        pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0));
  69.889 +                        temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0);
  69.890 +                }
  69.891 +                else
  69.892 +                {
  69.893 +//                 && ide->service) return ide.atastat[ide.board]|SERVICE_STAT;
  69.894 +//                pclog("Return status %02X\n",ide->atastat);
  69.895 +                        temp = ide->atastat;
  69.896 +                }
  69.897 +                break;
  69.898 +        }
  69.899 +//        if (ide_board) pclog("Read IDEb %04X %02X   %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board);
  69.900 +        return temp;
  69.901 +//        fatal("Bad IDE read %04X\n", addr);
  69.902 +}
  69.903 +
  69.904 +uint16_t readidew(int ide_board)
  69.905 +{
  69.906 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
  69.907 +        uint16_t temp;
  69.908 +#ifndef RPCEMU_IDE
  69.909 +/*        if (ide_board && (cr0&1) && !(eflags&VM_FLAG))
  69.910 +        {
  69.911 +//                pclog("Failed read IDEw %04X:%08X\n",CS,pc);
  69.912 +                return 0xFFFF;
  69.913 +        }*/
  69.914 +#endif
  69.915 +//        return 0xFFFF;
  69.916 +//        pclog("Read IDEw %04X %04X:%04X %02X %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins);
  69.917 +        
  69.918 +//if (idedebug) pclog("Read IDEW %08X\n",PC);
  69.919 +
  69.920 +        temp = ide->buffer[ide->pos >> 1];
  69.921 +	#ifdef _RPCEMU_BIG_ENDIAN
  69.922 +		temp=(temp>>8)|(temp<<8);
  69.923 +	#endif
  69.924 +        ide->pos+=2;
  69.925 +        if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen))
  69.926 +        {
  69.927 +//                pclog("Over! packlen %i %i\n",ide.packlen,ide.pos);
  69.928 +                ide->pos=0;
  69.929 +                if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6)
  69.930 +                {
  69.931 +//                        pclog("Call readCD\n");
  69.932 +                        callreadcd(ide);
  69.933 +                }
  69.934 +                else
  69.935 +                {
  69.936 +                        ide->atastat = READY_STAT | DSC_STAT;
  69.937 +                        ide->packetstatus=0;
  69.938 +                        if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY)
  69.939 +                        {
  69.940 +                                ide->secount--;
  69.941 +                                if (ide->secount)
  69.942 +                                {
  69.943 +                                        ide_next_sector(ide);
  69.944 +                                        ide->atastat = BUSY_STAT;
  69.945 +                                        idecallback[ide_board]=6*IDE_TIME;
  69.946 +//                                        callbackide(ide_board);
  69.947 +                                }
  69.948 +                        }
  69.949 +                }
  69.950 +        }
  69.951 +//        if (ide_board) pclog("Read IDEw %04X\n",temp);
  69.952 +        return temp;
  69.953 +}
  69.954 +
  69.955 +int times30=0;
  69.956 +void callbackide(int ide_board)
  69.957 +{
  69.958 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
  69.959 +        off64_t addr;
  69.960 +        int c;
  69.961 +        ext_ide = ide;
  69.962 +//        return;
  69.963 +        if (ide->command==0x30) times30++;
  69.964 +//        if (times30==2240) output=1;
  69.965 +        //if (times30==2471 && ide->command==0xA0) output=1;
  69.966 +///*if (ide_board) */pclog("CALLBACK %02X %i %i  %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]);
  69.967 +//        if (times30==1294)
  69.968 +//                output=1;
  69.969 +        if (ide->reset)
  69.970 +        {
  69.971 +                ide->atastat = READY_STAT | DSC_STAT;
  69.972 +                ide->error=1;
  69.973 +                ide->secount=1;
  69.974 +                ide->sector=1;
  69.975 +                ide->head=0;
  69.976 +                ide->cylinder=0;
  69.977 +                ide->reset = 0;
  69.978 +//                pclog("Reset callback\n");
  69.979 +                return;
  69.980 +        }
  69.981 +        switch (ide->command)
  69.982 +        {
  69.983 +                //Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h.
  69.984 +        case WIN_SRST: /*ATAPI Device Reset */
  69.985 +                ide->atastat = READY_STAT | DSC_STAT;
  69.986 +                ide->error=1; /*Device passed*/
  69.987 +                ide->secount = ide->sector = 1;
  69.988 +                if (IDE_DRIVE_IS_CDROM(ide)) {
  69.989 +                        ide->cylinder = 0xeb14;
  69.990 +                        ide->atastat = 0;
  69.991 +                } else {
  69.992 +                        ide->cylinder = 0;
  69.993 +                }
  69.994 +                ide_irq_raise(ide);
  69.995 +                if (IDE_DRIVE_IS_CDROM(ide))
  69.996 +                   ide->service = 0;
  69.997 +                return;
  69.998 +
  69.999 +        case WIN_RESTORE:
 69.1000 +        case WIN_SEEK:
 69.1001 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1002 +                        goto abort_cmd;
 69.1003 +                }
 69.1004 +//                pclog("Restore callback\n");
 69.1005 +                ide->atastat = READY_STAT | DSC_STAT;
 69.1006 +                ide_irq_raise(ide);
 69.1007 +                return;
 69.1008 +
 69.1009 +        case WIN_READ:
 69.1010 +        case WIN_READ_NORETRY:
 69.1011 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1012 +                        goto abort_cmd;
 69.1013 +                }
 69.1014 +                addr = ide_get_sector(ide) * 512;
 69.1015 +//                pclog("Read %i %i %i %08X\n",ide.cylinder,ide.head,ide.sector,addr);
 69.1016 +                /*                if (ide.cylinder || ide.head)
 69.1017 +                {
 69.1018 +                        fatal("Read from other cylinder/head");
 69.1019 +                }*/
 69.1020 +                fseeko64(ide->hdfile, addr, SEEK_SET);
 69.1021 +                fread(ide->buffer, 512, 1, ide->hdfile);
 69.1022 +                ide->pos=0;
 69.1023 +                ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
 69.1024 +//                pclog("Read sector callback %i %i %i offset %08X %i left %i %02X\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt,ide.atastat[ide.board]);
 69.1025 +//                if (addr) output=3;
 69.1026 +                ide_irq_raise(ide);
 69.1027 +#ifndef RPCEMU_IDE
 69.1028 +                readflash=1;
 69.1029 +#endif
 69.1030 +                return;
 69.1031 +
 69.1032 +        case WIN_WRITE:
 69.1033 +        case WIN_WRITE_NORETRY:
 69.1034 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1035 +                        goto abort_cmd;
 69.1036 +                }
 69.1037 +                addr = ide_get_sector(ide) * 512;
 69.1038 +//                pclog("Write sector callback %i %i %i offset %08X %i left %i\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt);
 69.1039 +                fseeko64(ide->hdfile, addr, SEEK_SET);
 69.1040 +                fwrite(ide->buffer, 512, 1, ide->hdfile);
 69.1041 +                ide_irq_raise(ide);
 69.1042 +                ide->secount--;
 69.1043 +                if (ide->secount)
 69.1044 +                {
 69.1045 +                        ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
 69.1046 +                        ide->pos=0;
 69.1047 +                        ide_next_sector(ide);
 69.1048 +                }
 69.1049 +                else
 69.1050 +                   ide->atastat = READY_STAT | DSC_STAT;
 69.1051 +#ifndef RPCEMU_IDE
 69.1052 +                readflash=1;
 69.1053 +#endif
 69.1054 +                return;
 69.1055 +
 69.1056 +        case WIN_VERIFY:
 69.1057 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1058 +                        goto abort_cmd;
 69.1059 +                }
 69.1060 +                ide->pos=0;
 69.1061 +                ide->atastat = READY_STAT | DSC_STAT;
 69.1062 +//                pclog("Read verify callback %i %i %i offset %08X %i left\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount);
 69.1063 +                ide_irq_raise(ide);
 69.1064 +#ifndef RPCEMU_IDE
 69.1065 +                readflash=1;
 69.1066 +#endif
 69.1067 +                return;
 69.1068 +
 69.1069 +        case WIN_FORMAT:
 69.1070 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1071 +                        goto abort_cmd;
 69.1072 +                }
 69.1073 +                addr = ide_get_sector(ide) * 512;
 69.1074 +//                pclog("Format cyl %i head %i offset %08X %08X %08X secount %i\n",ide.cylinder,ide.head,addr,addr>>32,addr,ide.secount);
 69.1075 +                fseeko64(ide->hdfile, addr, SEEK_SET);
 69.1076 +                memset(ide->buffer, 0, 512);
 69.1077 +                for (c=0;c<ide->secount;c++)
 69.1078 +                {
 69.1079 +                        fwrite(ide->buffer, 512, 1, ide->hdfile);
 69.1080 +                }
 69.1081 +                ide->atastat = READY_STAT | DSC_STAT;
 69.1082 +                ide_irq_raise(ide);
 69.1083 +#ifndef RPCEMU_IDE
 69.1084 +                readflash=1;
 69.1085 +#endif
 69.1086 +                return;
 69.1087 +
 69.1088 +        case WIN_DRIVE_DIAGNOSTICS:
 69.1089 +                ide->error=1; /*No error detected*/
 69.1090 +                ide->atastat = READY_STAT | DSC_STAT;
 69.1091 +                ide_irq_raise(ide);
 69.1092 +                return;
 69.1093 +
 69.1094 +        case WIN_SPECIFY: /* Initialize Drive Parameters */
 69.1095 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1096 +#ifndef RPCEMU_IDE
 69.1097 +                        pclog("IS CDROM - ABORT\n");
 69.1098 +#endif
 69.1099 +                        goto abort_cmd;
 69.1100 +                }
 69.1101 +                ide->spt=ide->secount;
 69.1102 +                ide->hpc=ide->head+1;
 69.1103 +                ide->atastat = READY_STAT | DSC_STAT;
 69.1104 +#ifndef RPCEMU_IDE
 69.1105 +//                pclog("SPECIFY - %i sectors per track, %i heads per cylinder  %i %i\n",ide->spt,ide->hpc,cur_ide[ide_board],ide_board);
 69.1106 +#endif
 69.1107 +                ide_irq_raise(ide);
 69.1108 +                return;
 69.1109 +
 69.1110 +        case WIN_PIDENTIFY: /* Identify Packet Device */
 69.1111 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1112 +//                        pclog("ATAPI identify\n");
 69.1113 +                        ide_atapi_identify(ide);
 69.1114 +                        ide->pos=0;
 69.1115 +                        ide->error=0;
 69.1116 +                        ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
 69.1117 +                        ide_irq_raise(ide);
 69.1118 +                        return;
 69.1119 +                }
 69.1120 +//                pclog("Not ATAPI\n");
 69.1121 +                goto abort_cmd;
 69.1122 +
 69.1123 +        case WIN_SETIDLE1: /* Idle */
 69.1124 +        case 0xEF:
 69.1125 +                goto abort_cmd;
 69.1126 +
 69.1127 +        case WIN_IDENTIFY: /* Identify Device */
 69.1128 +                if (IDE_DRIVE_IS_CDROM(ide)) {
 69.1129 +                        ide->secount=1;
 69.1130 +                        ide->sector=1;
 69.1131 +                        ide->cylinder=0xEB14;
 69.1132 +                        ide->drive=ide->head=0;
 69.1133 +                        goto abort_cmd;
 69.1134 +                }
 69.1135 +                if (ide->type != IDE_NONE)
 69.1136 +                {
 69.1137 +                        ide_identify(ide);
 69.1138 +                        ide->pos=0;
 69.1139 +                        ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT;
 69.1140 +//                pclog("ID callback\n");
 69.1141 +                        ide_irq_raise(ide);
 69.1142 +                }
 69.1143 +                return;
 69.1144 +
 69.1145 +        case WIN_PACKETCMD: /* ATAPI Packet */
 69.1146 +                if (!IDE_DRIVE_IS_CDROM(ide)) goto abort_cmd;
 69.1147 +//                pclog("Packet callback! %i %08X\n",ide->packetstatus,ide);
 69.1148 +                if (!ide->packetstatus)
 69.1149 +                {
 69.1150 +                        ide->pos=0;
 69.1151 +                        ide->secount = (uint8_t)((ide->secount&0xF8)|1);
 69.1152 +                        ide->atastat = DRQ_STAT |(ide->atastat&ERR_STAT);
 69.1153 +                        //ide_irq_raise(ide);
 69.1154 +//                        pclog("1 Preparing to recieve packet max DRQ count %04X\n",ide->cylinder);
 69.1155 +                }
 69.1156 +                else if (ide->packetstatus==1)
 69.1157 +                {
 69.1158 +                        ide->atastat = BUSY_STAT|(ide->atastat&ERR_STAT);
 69.1159 +//                        pclog("Running ATAPI command 2\n");
 69.1160 +                        atapicommand(ide_board);
 69.1161 +//                        exit(-1);
 69.1162 +                }
 69.1163 +                else if (ide->packetstatus==2)
 69.1164 +                {
 69.1165 +//                        pclog("packetstatus==2\n");
 69.1166 +                        ide->atastat = READY_STAT;
 69.1167 +                        ide->secount=3;
 69.1168 +                        ide_irq_raise(ide);
 69.1169 +//                        if (iomd.irqb.mask&2) output=1;
 69.1170 +                }
 69.1171 +                else if (ide->packetstatus==3)
 69.1172 +                {
 69.1173 +                        ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT);
 69.1174 +//                        rpclog("Recieve data packet 3! %02X\n",ide->atastat);
 69.1175 +                        ide_irq_raise(ide);
 69.1176 +                        ide->packetstatus=0xFF;
 69.1177 +                }
 69.1178 +                else if (ide->packetstatus==4)
 69.1179 +                {
 69.1180 +                        ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT);
 69.1181 +//                        pclog("Send data packet 4!\n");
 69.1182 +                        ide_irq_raise(ide);
 69.1183 +//                        ide.packetstatus=5;
 69.1184 +                        ide->pos=2;
 69.1185 +                }
 69.1186 +                else if (ide->packetstatus==5)
 69.1187 +                {
 69.1188 +//                        pclog("Packetstatus 5 !\n");
 69.1189 +                        atapicommand(ide_board);
 69.1190 +                }
 69.1191 +                else if (ide->packetstatus==6) /*READ CD callback*/
 69.1192 +                {
 69.1193 +                        ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT);
 69.1194 +//                        pclog("Recieve data packet 6!\n");
 69.1195 +                        ide_irq_raise(ide);
 69.1196 +//                        ide.packetstatus=0xFF;
 69.1197 +                }
 69.1198 +                else if (ide->packetstatus==0x80) /*Error callback*/
 69.1199 +                {
 69.1200 +//                        pclog("Packet error\n");
 69.1201 +                        ide->atastat = READY_STAT | ERR_STAT;
 69.1202 +                        ide_irq_raise(ide);
 69.1203 +                }
 69.1204 +                return;
 69.1205 +        }
 69.1206 +
 69.1207 +abort_cmd:
 69.1208 +	ide->atastat = READY_STAT | ERR_STAT | DSC_STAT;
 69.1209 +	ide->error = ABRT_ERR;
 69.1210 +	ide_irq_raise(ide);
 69.1211 +}
 69.1212 +
 69.1213 +/*ATAPI CD-ROM emulation
 69.1214 +  This mostly seems to work. It is implemented only on Windows at the moment as
 69.1215 +  I haven't had time to implement any interfaces for it in the generic gui.
 69.1216 +  It mostly depends on driver files - cdrom-iso.c for ISO image files (in theory
 69.1217 +  on any platform) and cdrom-ioctl.c for Win32 IOCTL access. There's an ATAPI
 69.1218 +  interface defined in ide.h.
 69.1219 +  There are a couple of bugs in the CD audio handling.
 69.1220 +  */
 69.1221 +
 69.1222 +struct
 69.1223 +{
 69.1224 +        int sensekey,asc,ascq;
 69.1225 +} atapi_sense;
 69.1226 +
 69.1227 +static void atapi_notready(IDE *ide)
 69.1228 +{
 69.1229 +        /*Medium not present is 02/3A/--*/
 69.1230 +        /*cylprecomp is error number*/
 69.1231 +        /*SENSE/ASC/ASCQ*/
 69.1232 +        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1233 +        ide->error = (SENSE_NOT_READY << 4) | ABRT_ERR;
 69.1234 +        if (ide->discchanged) {
 69.1235 +                ide->error |= MCR_ERR;
 69.1236 +                atapi_sense.sensekey=6;
 69.1237 +                atapi_sense.asc=0x28;
 69.1238 +        } else {
 69.1239 +                atapi_sense.sensekey=2;
 69.1240 +                atapi_sense.asc = ASC_MEDIUM_NOT_PRESENT;
 69.1241 +        }
 69.1242 +        ide->discchanged=0;
 69.1243 +        ide->packetstatus=0x80;
 69.1244 +        idecallback[ide->board]=50*IDE_TIME;
 69.1245 +}
 69.1246 +
 69.1247 +void atapi_discchanged()
 69.1248 +{
 69.1249 +        ext_ide->discchanged=1;
 69.1250 +        atapi_sense.sensekey=6;
 69.1251 +        atapi_sense.asc=0x28;
 69.1252 +}
 69.1253 +
 69.1254 +uint8_t atapi_prev;
 69.1255 +int toctimes=0;
 69.1256 +static void atapicommand(int ide_board)
 69.1257 +{
 69.1258 +        IDE *ide = &ide_drives[cur_ide[ide_board]];
 69.1259 +        uint8_t *idebufferb = (uint8_t *) ide->buffer;
 69.1260 +        int c;
 69.1261 +        int len;
 69.1262 +        int msf;
 69.1263 +        int pos=0;
 69.1264 +        unsigned char temp;
 69.1265 +#ifndef RPCEMU_IDE
 69.1266 +        pclog("New ATAPI command %02X %i\n",idebufferb[0],ins);
 69.1267 +#endif
 69.1268 +//        readflash=1;
 69.1269 +                msf=idebufferb[1]&2;
 69.1270 +                ide->cdlen=0;
 69.1271 +        if (idebufferb[0]!=GPCMD_REQUEST_SENSE)
 69.1272 +        {
 69.1273 +                atapi_prev=idebufferb[0];
 69.1274 +                atapi_sense.sensekey=0;
 69.1275 +                atapi_sense.asc=0;
 69.1276 +        }
 69.1277 +        switch (idebufferb[0])
 69.1278 +        {
 69.1279 +        case GPCMD_TEST_UNIT_READY:
 69.1280 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1281 +//                if (atapi->ready())
 69.1282 +//                {
 69.1283 +                        ide->packetstatus=2;
 69.1284 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1285 +//                }
 69.1286 +//                else
 69.1287 +//                {
 69.1288 +//                        pclog("Medium not present!\n");
 69.1289 +//                }
 69.1290 +                break;
 69.1291 +
 69.1292 +        case GPCMD_REQUEST_SENSE: /* Used by ROS 4+ */
 69.1293 +                /*Will return 18 bytes of 0*/
 69.1294 +                memset(idebufferb,0,512);
 69.1295 +//                switch (atapi_prev)
 69.1296 +//                {
 69.1297 +//                        case GPCMD_TEST_UNIT_READY:
 69.1298 +                        idebufferb[0]=0x80|0x70;
 69.1299 +                        idebufferb[2]=atapi_sense.sensekey;
 69.1300 +                        idebufferb[12]=atapi_sense.asc;
 69.1301 +                        idebufferb[13]=atapi_sense.ascq;
 69.1302 +//                        break;
 69.1303 +//
 69.1304 +//                        default:
 69.1305 +//                        fatal("Bad REQUEST_SENSE following command %02X\n",atapi_prev);
 69.1306 +//                }
 69.1307 +                ide->packetstatus=3;
 69.1308 +                ide->cylinder=18;
 69.1309 +                ide->secount=2;
 69.1310 +                ide->pos=0;
 69.1311 +                idecallback[ide_board]=60*IDE_TIME;
 69.1312 +                ide->packlen=18;
 69.1313 +                break;
 69.1314 +
 69.1315 +        case GPCMD_SET_SPEED:
 69.1316 +                ide->packetstatus=2;
 69.1317 +                idecallback[ide_board]=50*IDE_TIME;
 69.1318 +                break;
 69.1319 +
 69.1320 +        case GPCMD_READ_TOC_PMA_ATIP:
 69.1321 +//                pclog("Read TOC ready? %08X\n",ide);
 69.1322 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1323 +                toctimes++;
 69.1324 +//                if (toctimes==2) output=3;
 69.1325 +//                pclog("Read TOC %02X\n",idebufferb[9]);
 69.1326 +                switch (idebufferb[9]>>6)
 69.1327 +                {
 69.1328 +                        case 0: /*Normal*/
 69.1329 +                        len=idebufferb[8]+(idebufferb[7]<<8);
 69.1330 +                        len=atapi->readtoc(idebufferb,idebufferb[6],msf,len,0);
 69.1331 +                        break;
 69.1332 +                        case 1: /*Multi session*/
 69.1333 +                        len=idebufferb[8]+(idebufferb[7]<<8);
 69.1334 +                        atapi->readtoc_session(idebufferb,msf,len);
 69.1335 +                        idebufferb[0]=0; idebufferb[1]=0xA;
 69.1336 +                        break;
 69.1337 +                        default:
 69.1338 +                        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1339 +                        ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1340 +                        if (ide->discchanged) {
 69.1341 +                                ide->error |= MCR_ERR;
 69.1342 +                        }
 69.1343 +                        ide->discchanged=0;
 69.1344 +                        atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1345 +                        ide->packetstatus=0x80;
 69.1346 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1347 +                        break;
 69.1348 +/*                        pclog("Bad read TOC format\n");
 69.1349 +                        pclog("Packet data :\n");
 69.1350 +                        for (c=0;c<12;c++)
 69.1351 +                            pclog("%02X ",idebufferb[c]);
 69.1352 +                        pclog("\n");
 69.1353 +                        exit(-1);*/
 69.1354 +                }
 69.1355 +//                pclog("ATAPI buffer len %i\n",len);
 69.1356 +                ide->packetstatus=3;
 69.1357 +                ide->cylinder=len;
 69.1358 +                ide->secount=2;
 69.1359 +                ide->pos=0;
 69.1360 +                idecallback[ide_board]=60*IDE_TIME;
 69.1361 +                ide->packlen=len;
 69.1362 +                return;
 69.1363 +                
 69.1364 +        case GPCMD_READ_CD:
 69.1365 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1366 +//                pclog("Read CD : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]);
 69.1367 +                if (idebufferb[9]!=0x10)
 69.1368 +                {
 69.1369 +                        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1370 +                        ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1371 +                        if (ide->discchanged) {
 69.1372 +                                ide->error |= MCR_ERR;
 69.1373 +                        }
 69.1374 +                        ide->discchanged=0;
 69.1375 +                        atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1376 +                        ide->packetstatus=0x80;
 69.1377 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1378 +                        break;
 69.1379 +//                        pclog("Bad flags bits %02X\n",idebufferb[9]);
 69.1380 +//                        exit(-1);
 69.1381 +                }
 69.1382 +/*                if (idebufferb[6] || idebufferb[7] || (idebufferb[8]!=1))
 69.1383 +                {
 69.1384 +                        pclog("More than 1 sector!\n");
 69.1385 +                        exit(-1);
 69.1386 +                }*/
 69.1387 +                ide->cdlen=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8];
 69.1388 +                ide->cdpos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
 69.1389 +//                pclog("Read at %08X %08X\n",ide.cdpos,ide.cdpos*2048);
 69.1390 +                atapi->readsector(idebufferb,ide->cdpos);
 69.1391 +#ifndef RPCEMU_IDE
 69.1392 +                readflash=1;
 69.1393 +#endif
 69.1394 +                ide->cdpos++;
 69.1395 +                ide->cdlen--;
 69.1396 +                if (ide->cdlen>=0) ide->packetstatus=6;
 69.1397 +                else               ide->packetstatus=3;
 69.1398 +                ide->cylinder=2048;
 69.1399 +                ide->secount=2;
 69.1400 +                ide->pos=0;
 69.1401 +                idecallback[ide_board]=60*IDE_TIME;
 69.1402 +                ide->packlen=2048;
 69.1403 +                return;
 69.1404 +
 69.1405 +        case GPCMD_READ_10:
 69.1406 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1407 +//                pclog("Read 10 : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]);
 69.1408 +
 69.1409 +                ide->cdlen=(idebufferb[7]<<8)|idebufferb[8];
 69.1410 +                ide->cdpos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
 69.1411 +                if (!ide->cdlen)
 69.1412 +                {
 69.1413 +//                        pclog("All done - callback set\n");
 69.1414 +                        ide->packetstatus=2;
 69.1415 +                        idecallback[ide_board]=20*IDE_TIME;
 69.1416 +                        break;
 69.1417 +                }
 69.1418 +
 69.1419 +                atapi->readsector(idebufferb,ide->cdpos);
 69.1420 +#ifndef RPCEMU_IDE
 69.1421 +                readflash=1;
 69.1422 +#endif
 69.1423 +                ide->cdpos++;
 69.1424 +                ide->cdlen--;
 69.1425 +                if (ide->cdlen>=0) ide->packetstatus=6;
 69.1426 +                else               ide->packetstatus=3;
 69.1427 +                ide->cylinder=2048;
 69.1428 +                ide->secount=2;
 69.1429 +                ide->pos=0;
 69.1430 +                idecallback[ide_board]=60*IDE_TIME;
 69.1431 +                ide->packlen=2048;
 69.1432 +                return;
 69.1433 +
 69.1434 +        case GPCMD_READ_HEADER:
 69.1435 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1436 +                if (msf)
 69.1437 +                {
 69.1438 +                        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1439 +                        ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1440 +                        if (ide->discchanged) {
 69.1441 +                                ide->error |= MCR_ERR;
 69.1442 +                        }
 69.1443 +                        ide->discchanged=0;
 69.1444 +                        atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1445 +                        ide->packetstatus=0x80;
 69.1446 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1447 +                        break;
 69.1448 +//                        pclog("Read Header MSF!\n");
 69.1449 +//                        exit(-1);
 69.1450 +                }
 69.1451 +                for (c=0;c<4;c++) idebufferb[c+4]=idebufferb[c+2];
 69.1452 +                idebufferb[0]=1; /*2048 bytes user data*/
 69.1453 +                idebufferb[1]=idebufferb[2]=idebufferb[3]=0;
 69.1454 +                
 69.1455 +                ide->packetstatus=3;
 69.1456 +                ide->cylinder=8;
 69.1457 +                ide->secount=2;
 69.1458 +                ide->pos=0;
 69.1459 +                idecallback[ide_board]=60*IDE_TIME;
 69.1460 +                ide->packlen=8;
 69.1461 +                return;
 69.1462 +                
 69.1463 +        case GPCMD_MODE_SENSE_10:
 69.1464 +//                output=3;
 69.1465 +//                pclog("Mode sense - ready?\n");
 69.1466 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1467 +                        len=(idebufferb[8]|(idebufferb[7]<<8));
 69.1468 +
 69.1469 +//pclog("Mode sense %02X %i\n",idebufferb[2],len);
 69.1470 +                temp=idebufferb[2];
 69.1471 +//                switch (idebufferb[2])
 69.1472 +//                {
 69.1473 +//                        case GPMODE_ALL_PAGES:
 69.1474 +//                        case GPMODE_CAPABILITIES_PAGE:
 69.1475 +                        for (c=0;c<len;c++) idebufferb[c]=0;
 69.1476 +                        len = ide_atapi_mode_sense(ide,8,temp);
 69.1477 +//                        break;
 69.1478 +//                        default:
 69.1479 +//                        for (c=0;c<len;c++) idebufferb[c]=0;
 69.1480 +/*                        pclog("Bad mode sense\n");
 69.1481 +                        pclog("Packet data :\n");
 69.1482 +                        for (c=0;c<12;c++)
 69.1483 +                            pclog("%02X\n",idebufferb[c]);
 69.1484 +                        exit(-1);*/
 69.1485 +//                }
 69.1486 +
 69.1487 +                        /*Set mode parameter header - bytes 0 & 1 are data length (filled out later),
 69.1488 +                          byte 2 is media type*/
 69.1489 +                idebufferb[0]=len>>8;
 69.1490 +                idebufferb[1]=len&255;
 69.1491 +                idebufferb[2]=3; /*120mm data CD-ROM*/
 69.1492 +//        pclog("ATAPI buffer len %i\n",len);
 69.1493 +/*        for (c=0;c<len;c++) pclog("%02X ",idebufferb[c]);
 69.1494 +        pclog("\n");*/
 69.1495 +        ide->packetstatus=3;
 69.1496 +        ide->cylinder=len;
 69.1497 +        ide->secount=2;
 69.1498 +//        ide.atastat = DRQ_STAT;
 69.1499 +        ide->pos=0;
 69.1500 +                idecallback[ide_board]=1000*IDE_TIME;
 69.1501 +                ide->packlen=len;
 69.1502 +//        pclog("Sending packet\n");
 69.1503 +        return;
 69.1504 +
 69.1505 +        case GPCMD_MODE_SELECT_10:
 69.1506 +//                if (!atapi->ready()) { atapi_notready(); return; }
 69.1507 +                if (ide->packetstatus==5)
 69.1508 +                {
 69.1509 +                        ide->atastat = 0;
 69.1510 +//                        pclog("Recieve data packet!\n");
 69.1511 +                        ide_irq_raise(ide);
 69.1512 +                        ide->packetstatus=0xFF;
 69.1513 +                        ide->pos=0;
 69.1514 +  //                      pclog("Length - %02X%02X\n",idebufferb[0],idebufferb[1]);
 69.1515 +//                        pclog("Page %02X length %02X\n",idebufferb[8],idebufferb[9]);
 69.1516 +                }
 69.1517 +                else
 69.1518 +                {
 69.1519 +                        len=(idebufferb[7]<<8)|idebufferb[8];
 69.1520 +                        ide->packetstatus=4;
 69.1521 +                        ide->cylinder=len;
 69.1522 +                        ide->secount=2;
 69.1523 +                        ide->pos=0;
 69.1524 +                        idecallback[ide_board]=6*IDE_TIME;
 69.1525 +                        ide->packlen=len;
 69.1526 +/*                        pclog("Waiting for ARM to send packet %i\n",len);
 69.1527 +                pclog("Packet data :\n");
 69.1528 +                for (c=0;c<12;c++)
 69.1529 +                    pclog("%02X ",idebufferb[c]);
 69.1530 +                    pclog("\n");*/
 69.1531 +                }
 69.1532 +                return;
 69.1533 +
 69.1534 +        case GPCMD_PLAY_AUDIO_12:
 69.1535 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1536 +                /*This is apparently deprecated in the ATAPI spec, and apparently
 69.1537 +                  has been since 1995 (!). Hence I'm having to guess most of it*/
 69.1538 +                pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
 69.1539 +                len=(idebufferb[7]<<16)|(idebufferb[8]<<8)|idebufferb[9];
 69.1540 +                atapi->playaudio(pos,len,0);
 69.1541 +                ide->packetstatus=2;
 69.1542 +                idecallback[ide_board]=50*IDE_TIME;
 69.1543 +                break;
 69.1544 +
 69.1545 +        case GPCMD_PLAY_AUDIO_MSF:
 69.1546 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1547 +                pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
 69.1548 +                len=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8];
 69.1549 +                atapi->playaudio(pos,len,1);
 69.1550 +                ide->packetstatus=2;
 69.1551 +                idecallback[ide_board]=50*IDE_TIME;
 69.1552 +                break;
 69.1553 +                
 69.1554 +        case GPCMD_READ_SUBCHANNEL:
 69.1555 +                if (!atapi->ready()) { /*pclog("Read subchannel not ready\n"); */atapi_notready(ide); return; }
 69.1556 +                temp=idebufferb[2]&0x40;
 69.1557 +                if (idebufferb[3]!=1)
 69.1558 +                {
 69.1559 +//                        pclog("Read subchannel check condition %02X\n",idebufferb[3]);
 69.1560 +                        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1561 +                        ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1562 +                        if (ide->discchanged) {
 69.1563 +                                ide->error |= MCR_ERR;
 69.1564 +                        }
 69.1565 +                        ide->discchanged=0;
 69.1566 +                        atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1567 +                        ide->packetstatus=0x80;
 69.1568 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1569 +                        break;
 69.1570 +/*                        pclog("Bad read subchannel!\n");
 69.1571 +                        pclog("Packet data :\n");
 69.1572 +                        for (c=0;c<12;c++)
 69.1573 +                            pclog("%02X\n",idebufferb[c]);
 69.1574 +                        dumpregs();
 69.1575 +                        exit(-1);*/
 69.1576 +                }
 69.1577 +                pos=0;
 69.1578 +                idebufferb[pos++]=0;
 69.1579 +                idebufferb[pos++]=0; /*Audio status*/
 69.1580 +                idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/
 69.1581 +                idebufferb[pos++]=1; /*Format code*/
 69.1582 +                idebufferb[1]=atapi->getcurrentsubchannel(&idebufferb[5],msf);
 69.1583 +//                pclog("Read subchannel complete - audio status %02X\n",idebufferb[1]);
 69.1584 +                len=11+5;
 69.1585 +                if (!temp) len=4;
 69.1586 +                ide->packetstatus=3;
 69.1587 +                ide->cylinder=len;
 69.1588 +                ide->secount=2;
 69.1589 +                ide->pos=0;
 69.1590 +                idecallback[ide_board]=1000*IDE_TIME;
 69.1591 +                ide->packlen=len;
 69.1592 +                break;
 69.1593 +
 69.1594 +        case GPCMD_START_STOP_UNIT:
 69.1595 +                if (idebufferb[4]!=2 && idebufferb[4]!=3 && idebufferb[4])
 69.1596 +                {
 69.1597 +                        ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1598 +                        ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1599 +                        if (ide->discchanged) {
 69.1600 +                                ide->error |= MCR_ERR;
 69.1601 +                        }
 69.1602 +                        ide->discchanged=0;
 69.1603 +                        atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1604 +                        ide->packetstatus=0x80;
 69.1605 +                        idecallback[ide_board]=50*IDE_TIME;
 69.1606 +                        break;
 69.1607 +/*                        pclog("Bad start/stop unit command\n");
 69.1608 +                        pclog("Packet data :\n");
 69.1609 +                        for (c=0;c<12;c++)
 69.1610 +                            pclog("%02X\n",idebufferb[c]);
 69.1611 +                        exit(-1);*/
 69.1612 +                }
 69.1613 +                if (!idebufferb[4])        atapi->stop();
 69.1614 +                else if (idebufferb[4]==2) atapi->eject();
 69.1615 +                else                       atapi->load();
 69.1616 +                ide->packetstatus=2;
 69.1617 +                idecallback[ide_board]=50*IDE_TIME;
 69.1618 +                break;
 69.1619 +                
 69.1620 +        case GPCMD_INQUIRY:
 69.1621 +                idebufferb[0] = 5; /*CD-ROM*/
 69.1622 +                idebufferb[1] = 0x80; /*Removable*/
 69.1623 +                idebufferb[2] = 0;
 69.1624 +                idebufferb[3] = 0x21;
 69.1625 +                idebufferb[4] = 31;
 69.1626 +                idebufferb[5] = 0;
 69.1627 +                idebufferb[6] = 0;
 69.1628 +                idebufferb[7] = 0;
 69.1629 +#ifdef RPCEMU_IDE
 69.1630 +                ide_padstr8(idebufferb + 8, 8, "RPCemu"); /* Vendor */
 69.1631 +                ide_padstr8(idebufferb + 16, 16, "RPCemuCD"); /* Product */
 69.1632 +#else
 69.1633 +                ide_padstr8(idebufferb + 8, 8, "PCem"); /* Vendor */
 69.1634 +                ide_padstr8(idebufferb + 16, 16, "PCemCD"); /* Product */
 69.1635 +#endif
 69.1636 +                ide_padstr8(idebufferb + 32, 4, "v1.0"); /* Revision */
 69.1637 +
 69.1638 +                len=36;
 69.1639 +                ide->packetstatus=3;
 69.1640 +                ide->cylinder=len;
 69.1641 +                ide->secount=2;
 69.1642 +                ide->pos=0;
 69.1643 +                idecallback[ide_board]=60*IDE_TIME;
 69.1644 +                ide->packlen=len;
 69.1645 +                break;
 69.1646 +
 69.1647 +        case GPCMD_PREVENT_REMOVAL:
 69.1648 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1649 +                ide->packetstatus=2;
 69.1650 +                idecallback[ide_board]=50*IDE_TIME;
 69.1651 +                break;
 69.1652 +
 69.1653 +        case GPCMD_PAUSE_RESUME:
 69.1654 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1655 +                if (idebufferb[8]&1) atapi->resume();
 69.1656 +                else                 atapi->pause();
 69.1657 +                ide->packetstatus=2;
 69.1658 +                idecallback[ide_board]=50*IDE_TIME;
 69.1659 +                break;
 69.1660 +
 69.1661 +        case GPCMD_SEEK:
 69.1662 +                if (!atapi->ready()) { atapi_notready(ide); return; }
 69.1663 +                pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5];
 69.1664 +                atapi->seek(pos);
 69.1665 +                ide->packetstatus=2;
 69.1666 +                idecallback[ide_board]=50*IDE_TIME;
 69.1667 +                break;
 69.1668 +
 69.1669 +        case GPCMD_SEND_DVD_STRUCTURE:
 69.1670 +        default:
 69.1671 +                ide->atastat = READY_STAT | ERR_STAT;    /*CHECK CONDITION*/
 69.1672 +                ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR;
 69.1673 +                if (ide->discchanged) {
 69.1674 +                        ide->error |= MCR_ERR;
 69.1675 +                }
 69.1676 +                ide->discchanged=0;
 69.1677 +                atapi_sense.asc = ASC_ILLEGAL_OPCODE;
 69.1678 +                ide->packetstatus=0x80;
 69.1679 +                idecallback[ide_board]=50*IDE_TIME;
 69.1680 +                break;
 69.1681 +                
 69.1682 +/*                default:
 69.1683 +                pclog("Bad ATAPI command %02X\n",idebufferb[0]);
 69.1684 +                pclog("Packet data :\n");
 69.1685 +                for (c=0;c<12;c++)
 69.1686 +                    pclog("%02X\n",idebufferb[c]);
 69.1687 +                exit(-1);*/
 69.1688 +        }
 69.1689 +}
 69.1690 +
 69.1691 +static void callreadcd(IDE *ide)
 69.1692 +{
 69.1693 +        ide_irq_lower(ide);
 69.1694 +        if (ide->cdlen<=0)
 69.1695 +        {
 69.1696 +//                pclog("All done - callback set\n");
 69.1697 +                ide->packetstatus=2;
 69.1698 +                idecallback[ide->board]=20*IDE_TIME;
 69.1699 +                return;
 69.1700 +        }
 69.1701 +//        pclog("Continue readcd! %i blocks left\n",ide->cdlen);
 69.1702 +        ide->atastat = BUSY_STAT;
 69.1703 +        
 69.1704 +        atapi->readsector((uint8_t *) ide->buffer, ide->cdpos);
 69.1705 +#ifndef RPCEMU_IDE
 69.1706 +                readflash=1;
 69.1707 +#endif
 69.1708 +                ide->cdpos++;
 69.1709 +                ide->cdlen--;
 69.1710 +                ide->packetstatus=6;
 69.1711 +                ide->cylinder=2048;
 69.1712 +                ide->secount=2;
 69.1713 +                ide->pos=0;
 69.1714 +                idecallback[ide->board]=60*IDE_TIME;
 69.1715 +                ide->packlen=2048;
 69.1716 +}
 69.1717 +
 69.1718 +
 69.1719 +
 69.1720 +void ide_write_pri(uint16_t addr, uint8_t val)
 69.1721 +{
 69.1722 +        writeide(0, addr, val);
 69.1723 +}
 69.1724 +void ide_write_pri_w(uint16_t addr, uint16_t val)
 69.1725 +{
 69.1726 +        writeidew(0, val);
 69.1727 +}
 69.1728 +uint8_t ide_read_pri(uint16_t addr)
 69.1729 +{
 69.1730 +        return readide(0, addr);
 69.1731 +}
 69.1732 +uint16_t ide_read_pri_w(uint16_t addr)
 69.1733 +{
 69.1734 +        return readidew(0);
 69.1735 +}
 69.1736 +
 69.1737 +void ide_write_sec(uint16_t addr, uint8_t val)
 69.1738 +{
 69.1739 +        writeide(1, addr, val);
 69.1740 +}
 69.1741 +void ide_write_sec_w(uint16_t addr, uint16_t val)
 69.1742 +{
 69.1743 +        writeidew(1, val);
 69.1744 +}
 69.1745 +uint8_t ide_read_sec(uint16_t addr)
 69.1746 +{
 69.1747 +        return readide(1, addr);
 69.1748 +}
 69.1749 +uint16_t ide_read_sec_w(uint16_t addr)
 69.1750 +{
 69.1751 +        return readidew(1);
 69.1752 +}
 69.1753 +
 69.1754 +void ide_init()
 69.1755 +{
 69.1756 +        io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, NULL, ide_write_pri, ide_write_pri_w, NULL);
 69.1757 +        io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL,           NULL, ide_write_pri, NULL,            NULL);
 69.1758 +        io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, NULL, ide_write_sec, ide_write_sec_w, NULL);
 69.1759 +        io_sethandler(0x0376, 0x0001, ide_read_sec, NULL,           NULL, ide_write_sec, NULL,            NULL);
 69.1760 +}
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/src/ide.h	Sun Apr 21 14:54:35 2013 +0100
    70.3 @@ -0,0 +1,42 @@
    70.4 +#ifndef __IDE__
    70.5 +#define __IDE__
    70.6 +
    70.7 +struct IDE;
    70.8 +
    70.9 +extern void writeide(int ide_board, uint16_t addr, uint8_t val);
   70.10 +extern void writeidew(int ide_board, uint16_t val);
   70.11 +extern uint8_t readide(int ide_board, uint16_t addr);
   70.12 +extern uint16_t readidew(int ide_board);
   70.13 +extern void callbackide(int ide_board);
   70.14 +extern void resetide(void);
   70.15 +extern void ide_init();
   70.16 +
   70.17 +/*ATAPI stuff*/
   70.18 +typedef struct ATAPI
   70.19 +{
   70.20 +        int (*ready)(void);
   70.21 +        int (*readtoc)(uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single);
   70.22 +        void (*readtoc_session)(uint8_t *b, int msf, int maxlen);
   70.23 +        uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf);
   70.24 +        void (*readsector)(uint8_t *b, int sector);
   70.25 +        void (*playaudio)(uint32_t pos, uint32_t len, int ismsf);
   70.26 +        void (*seek)(uint32_t pos);
   70.27 +        void (*load)(void);
   70.28 +        void (*eject)(void);
   70.29 +        void (*pause)(void);
   70.30 +        void (*resume)(void);
   70.31 +        void (*stop)(void);
   70.32 +        void (*exit)(void);
   70.33 +} ATAPI;
   70.34 +
   70.35 +extern ATAPI *atapi;
   70.36 +
   70.37 +void atapi_discchanged();
   70.38 +
   70.39 +extern int ideboard;
   70.40 +
   70.41 +extern int idecallback[2];
   70.42 +
   70.43 +extern char ide_fn[2][512];
   70.44 +
   70.45 +#endif //__IDE__
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/src/io.c	Sun Apr 21 14:54:35 2013 +0100
    71.3 @@ -0,0 +1,196 @@
    71.4 +#include "ibm.h"
    71.5 +#include "ide.h"
    71.6 +#include "video.h"
    71.7 +#include "cpu.h"
    71.8 +
    71.9 +uint8_t  (*port_inb[0x10000][2])(uint16_t addr);
   71.10 +uint16_t (*port_inw[0x10000][2])(uint16_t addr);
   71.11 +uint32_t (*port_inl[0x10000][2])(uint16_t addr);
   71.12 +
   71.13 +void (*port_outb[0x10000][2])(uint16_t addr, uint8_t  val);
   71.14 +void (*port_outw[0x10000][2])(uint16_t addr, uint16_t val);
   71.15 +void (*port_outl[0x10000][2])(uint16_t addr, uint32_t val);
   71.16 +
   71.17 +void io_init()
   71.18 +{
   71.19 +        int c;
   71.20 +        for (c = 0; c < 0x10000; c++)
   71.21 +        {
   71.22 +                port_inb[c][0]  = port_inw[c][0]  = port_inl[c][0]  = NULL;
   71.23 +                port_outb[c][0] = port_outw[c][0] = port_outl[c][0] = NULL;
   71.24 +                port_inb[c][1]  = port_inw[c][1]  = port_inl[c][1]  = NULL;
   71.25 +                port_outb[c][1] = port_outw[c][1] = port_outl[c][1] = NULL;
   71.26 +        }
   71.27 +}
   71.28 +
   71.29 +void io_sethandler(uint16_t base, int size, 
   71.30 +                   uint8_t  (*inb)(uint16_t addr), 
   71.31 +                   uint16_t (*inw)(uint16_t addr), 
   71.32 +                   uint32_t (*inl)(uint16_t addr), 
   71.33 +                   void (*outb)(uint16_t addr, uint8_t  val),
   71.34 +                   void (*outw)(uint16_t addr, uint16_t val),
   71.35 +                   void (*outl)(uint16_t addr, uint32_t val))
   71.36 +{
   71.37 +        int c;
   71.38 +        for (c = 0; c < size; c++)
   71.39 +        {
   71.40 +                if      (!port_inb[ base + c][0]) port_inb[ base + c][0] = inb;
   71.41 +                else if (!port_inb[ base + c][1]) port_inb[ base + c][1] = inb;                
   71.42 +                if      (!port_inw[ base + c][0]) port_inw[ base + c][0] = inw;
   71.43 +                else if (!port_inw[ base + c][1]) port_inw[ base + c][1] = inw;
   71.44 +                if      (!port_inl[ base + c][0]) port_inl[ base + c][0] = inl;
   71.45 +                else if (!port_inl[ base + c][1]) port_inl[ base + c][1] = inl;
   71.46 +                if      (!port_outb[base + c][0]) port_outb[base + c][0] = outb;
   71.47 +                else if (!port_outb[base + c][1]) port_outb[base + c][1] = outb;                
   71.48 +                if      (!port_outw[base + c][0]) port_outw[base + c][0] = outw;
   71.49 +                else if (!port_outw[base + c][1]) port_outw[base + c][1] = outw;
   71.50 +                if      (!port_outl[base + c][0]) port_outl[base + c][0] = outl;
   71.51 +                else if (!port_outl[base + c][1]) port_outl[base + c][1] = outl;
   71.52 +        }
   71.53 +}
   71.54 +
   71.55 +void io_removehandler(uint16_t base, int size, 
   71.56 +                   uint8_t  (*inb)(uint16_t addr), 
   71.57 +                   uint16_t (*inw)(uint16_t addr), 
   71.58 +                   uint32_t (*inl)(uint16_t addr), 
   71.59 +                   void (*outb)(uint16_t addr, uint8_t  val),
   71.60 +                   void (*outw)(uint16_t addr, uint16_t val),
   71.61 +                   void (*outl)(uint16_t addr, uint32_t val))
   71.62 +{
   71.63 +        int c;
   71.64 +        for (c = 0; c < size; c++)
   71.65 +        {
   71.66 +                if (port_inb[ base + c][0] == inb)
   71.67 +                   port_inb[ base + c][0] = NULL;
   71.68 +                if (port_inb[ base + c][1] == inb)
   71.69 +                   port_inb[ base + c][1] = NULL;
   71.70 +                if (port_inw[ base + c][0] == inw)
   71.71 +                   port_inw[ base + c][0] = NULL;
   71.72 +                if (port_inw[ base + c][1] == inw)
   71.73 +                   port_inw[ base + c][1] = NULL;
   71.74 +                if (port_inl[ base + c][0] == inl)
   71.75 +                   port_inl[ base + c][0] = NULL;
   71.76 +                if (port_inl[ base + c][1] == inl)
   71.77 +                   port_inl[ base + c][1] = NULL;
   71.78 +                if (port_outb[ base + c][0] == outb)
   71.79 +                   port_outb[ base + c][0] = NULL;
   71.80 +                if (port_outb[ base + c][1] == outb)
   71.81 +                   port_outb[ base + c][1] = NULL;
   71.82 +                if (port_outw[ base + c][0] == outw)
   71.83 +                   port_outw[ base + c][0] = NULL;
   71.84 +                if (port_outw[ base + c][1] == outw)
   71.85 +                   port_outw[ base + c][1] = NULL;
   71.86 +                if (port_outl[ base + c][0] == outl)
   71.87 +                   port_outl[ base + c][0] = NULL;
   71.88 +                if (port_outl[ base + c][1] == outl)
   71.89 +                   port_outl[ base + c][1] = NULL;
   71.90 +        }
   71.91 +}
   71.92 +
   71.93 +uint8_t cgamode,cgastat=0,cgacol;
   71.94 +int hsync;
   71.95 +uint8_t lpt2dat;
   71.96 +int sw9;
   71.97 +int t237=0;
   71.98 +uint8_t inb(uint16_t port)
   71.99 +{
  71.100 +        uint8_t temp = 0xff;
  71.101 +        int tempi;
  71.102 +        if (port_inb[port][0])
  71.103 +           temp &= port_inb[port][0](port);
  71.104 +        if (port_inb[port][1])
  71.105 +           temp &= port_inb[port][1](port);
  71.106 +        return temp;
  71.107 +        
  71.108 +        if (port&0x80) sw9=2;
  71.109 +//        if ((port&0x3F0)==0x3D0) printf("Video access read %03X %04X:%04X\n",port,cs>>4,pc);
  71.110 +//        if (cs<0xF0000 || cs>0x100000) printf("IN %04X %04X(%06X):%08X\n",port,CS,cs,pc);
  71.111 +//        /*if (output==3) */printf("IN %04X %04X:%04X\n",port,CS,pc);
  71.112 +//        if (port == 0x23) pclog("IN %04X %04X:%08X\n", port, CS, pc);
  71.113 +        switch (port)
  71.114 +        {
  71.115 +                case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/
  71.116 +                if (sbtype>=SBPRO) return readsb(port);
  71.117 +                if (GAMEBLASTER) return readcms(port);
  71.118 +                return 0xFF;
  71.119 +        }
  71.120 +//        printf("Bad IN port %04X %04X:%04X\n",port,cs>>4,pc);
  71.121 +        return 0xff;
  71.122 +        /*dumpregs();
  71.123 +        exit(-1);*/
  71.124 +}
  71.125 +
  71.126 +/*uint8_t inb(uint16_t port)
  71.127 +{
  71.128 +        uint8_t temp = _inb(port);
  71.129 +//        if (port != 0x61) pclog("IN %04X %02X %04X(%08X):%08X %f   %04X %i %i\n", port, temp, CS, cs, pc, pit.c[1], CX, keybsenddelay, GetTickCount());
  71.130 +        return temp;
  71.131 +}*/
  71.132 +
  71.133 +uint8_t cpu_readport(uint32_t port) { return inb(port); }
  71.134 +
  71.135 +void outb(uint16_t port, uint8_t val)
  71.136 +{
  71.137 +//        /*if (output==3) */printf("OUT %04X %02X %04X(%08X):%08X %i %i\n", port, val, CS, cs, pc, ins, GetTickCount());
  71.138 +        if (port_outb[port][0])
  71.139 +           port_outb[port][0](port, val);
  71.140 +        if (port_outb[port][1])
  71.141 +           port_outb[port][1](port, val);
  71.142 +        return;
  71.143 +        switch (port)
  71.144 +        {
  71.145 +                case 0x220: case 0x221: case 0x222: case 0x223: /*Gameblaster*/
  71.146 +                if (GAMEBLASTER) writecms(port,val);
  71.147 +                return;
  71.148 +        }
  71.149 +        pclog("OUT %04X %02X %04X:%08X\n",port,val,CS,pc);
  71.150 +}
  71.151 +
  71.152 +uint16_t inw(uint16_t port)
  71.153 +{
  71.154 +        if (port_inw[port][0])
  71.155 +           return port_inw[port][0](port);
  71.156 +        if (port_inw[port][1])
  71.157 +           return port_inw[port][1](port);
  71.158 +           
  71.159 +        return inb(port) | (inb(port + 1) << 8);
  71.160 +}
  71.161 +
  71.162 +void outw(uint16_t port, uint16_t val)
  71.163 +{
  71.164 +//        printf("OUTW %04X %04X %04X:%08X\n",port,val, CS, pc);
  71.165 +        if (port_outw[port][0])
  71.166 +           port_outw[port][0](port, val);
  71.167 +        if (port_outw[port][1])
  71.168 +           port_outw[port][1](port, val);
  71.169 +
  71.170 +        if (port_outw[port][0] || port_outw[port][1])
  71.171 +           return;
  71.172 +
  71.173 +        outb(port,val);
  71.174 +        outb(port+1,val>>8);
  71.175 +}
  71.176 +
  71.177 +uint32_t inl(uint16_t port)
  71.178 +{
  71.179 +        if (port_inl[port][0])
  71.180 +           return port_inl[port][0](port);
  71.181 +        if (port_inl[port][1])
  71.182 +           return port_inl[port][1](port);
  71.183 +           
  71.184 +        return inw(port) | (inw(port + 2) << 16);
  71.185 +}
  71.186 +
  71.187 +void outl(uint16_t port, uint32_t val)
  71.188 +{
  71.189 +        if (port_outl[port][0])
  71.190 +           port_outl[port][0](port, val);
  71.191 +        if (port_outl[port][1])
  71.192 +           port_outl[port][1](port, val);
  71.193 +
  71.194 +        if (port_outl[port][0] || port_outl[port][1])
  71.195 +           return;
  71.196 +                
  71.197 +        outw(port, val);
  71.198 +        outw(port + 2, val >> 16);
  71.199 +}
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/src/io.h	Sun Apr 21 14:54:35 2013 +0100
    72.3 @@ -0,0 +1,17 @@
    72.4 +void io_init();
    72.5 +
    72.6 +void io_sethandler(uint16_t base, int size, 
    72.7 +                   uint8_t  (*inb)(uint16_t addr), 
    72.8 +                   uint16_t (*inw)(uint16_t addr), 
    72.9 +                   uint32_t (*inl)(uint16_t addr), 
   72.10 +                   void (*outb)(uint16_t addr, uint8_t  val),
   72.11 +                   void (*outw)(uint16_t addr, uint16_t val),
   72.12 +                   void (*outl)(uint16_t addr, uint32_t val));
   72.13 +                   
   72.14 +void io_removehandler(uint16_t base, int size, 
   72.15 +                   uint8_t  (*inb)(uint16_t addr), 
   72.16 +                   uint16_t (*inw)(uint16_t addr), 
   72.17 +                   uint32_t (*inl)(uint16_t addr), 
   72.18 +                   void (*outb)(uint16_t addr, uint8_t  val),
   72.19 +                   void (*outw)(uint16_t addr, uint16_t val),
   72.20 +                   void (*outl)(uint16_t addr, uint32_t val));
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/src/jim.c	Sun Apr 21 14:54:35 2013 +0100
    73.3 @@ -0,0 +1,78 @@
    73.4 +#include <stdio.h>
    73.5 +#include <string.h>
    73.6 +#include "ibm.h"
    73.7 +
    73.8 +uint8_t europcdat[16];
    73.9 +struct 
   73.10 +{
   73.11 +        uint8_t dat[16];
   73.12 +        int stat;
   73.13 +        int addr;
   73.14 +} europc_rtc;
   73.15 +
   73.16 +void writejim(uint16_t addr, uint8_t val)
   73.17 +{
   73.18 +        if ((addr&0xFF0)==0x250) europcdat[addr&0xF]=val;
   73.19 +        switch (addr)
   73.20 +        {
   73.21 +                case 0x25A:
   73.22 +//                        printf("Write RTC stat %i val %02X\n",europc_rtc.stat,val);
   73.23 +                switch (europc_rtc.stat)
   73.24 +                {
   73.25 +                        case 0:
   73.26 +                        europc_rtc.addr=val&0xF;
   73.27 +                        europc_rtc.stat++;
   73.28 +//                        printf("RTC addr now %02X - contents %02X\n",val&0xF,europc_rtc.dat[europc_rtc.addr]);
   73.29 +                        break;
   73.30 +                        case 1:
   73.31 +                        europc_rtc.dat[europc_rtc.addr]=(europc_rtc.dat[europc_rtc.addr]&0xF)|(val<<4);
   73.32 +                        europc_rtc.stat++;
   73.33 +                        break;
   73.34 +                        case 2:
   73.35 +                        europc_rtc.dat[europc_rtc.addr]=(europc_rtc.dat[europc_rtc.addr]&0xF0)|(val&0xF);
   73.36 +                        europc_rtc.stat=0;
   73.37 +                        break;
   73.38 +                }
   73.39 +                break;
   73.40 +        }
   73.41 +//        printf("Write JIM %04X %02X\n",addr,val);
   73.42 +}
   73.43 +
   73.44 +uint8_t readjim(uint16_t addr)
   73.45 +{
   73.46 +//        printf("Read JIM %04X\n",addr);
   73.47 +        switch (addr)
   73.48 +        {
   73.49 +                case 0x250: case 0x251: case 0x252: case 0x253: return 0;
   73.50 +                case 0x254: case 0x255: case 0x256: case 0x257: return europcdat[addr&0xF];
   73.51 +                case 0x25A:
   73.52 +                if (europc_rtc.stat==1)
   73.53 +                {
   73.54 +                        europc_rtc.stat=2;
   73.55 +                        return europc_rtc.dat[europc_rtc.addr]>>4;
   73.56 +                }
   73.57 +                if (europc_rtc.stat==2)
   73.58 +                {
   73.59 +                        europc_rtc.stat=0;
   73.60 +                        return europc_rtc.dat[europc_rtc.addr]&0xF;
   73.61 +                }
   73.62 +                return 0;
   73.63 +        }
   73.64 +        return 0;
   73.65 +}
   73.66 +
   73.67 +void jim_init()
   73.68 +{
   73.69 +        uint8_t viddat;
   73.70 +        memset(europc_rtc.dat,0,16);
   73.71 +        europc_rtc.dat[0xF]=1;
   73.72 +        europc_rtc.dat[3]=1;
   73.73 +        europc_rtc.dat[4]=1;
   73.74 +        europc_rtc.dat[5]=0x88;
   73.75 +        if (gfxcard==GFX_CGA) viddat=0x12;
   73.76 +        else if (gfxcard==GFX_MDA || gfxcard==GFX_HERCULES) viddat=3;
   73.77 +        else viddat=0x10;
   73.78 +        europc_rtc.dat[0xB]=viddat;
   73.79 +        europc_rtc.dat[0xD]=viddat; /*Checksum*/
   73.80 +        io_sethandler(0x250, 0x10, readjim, NULL, NULL, writejim, NULL, NULL);
   73.81 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/src/jim.h	Sun Apr 21 14:54:35 2013 +0100
    74.3 @@ -0,0 +1,1 @@
    74.4 +void jim_init();
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/src/keyboard.c	Sun Apr 21 14:54:35 2013 +0100
    75.3 @@ -0,0 +1,280 @@
    75.4 +#include "ibm.h"
    75.5 +#include "plat-keyboard.h"
    75.6 +#include "keyboard.h"
    75.7 +
    75.8 +int keybsendcallback = 0;
    75.9 +
   75.10 +typedef struct
   75.11 +{
   75.12 +        int scancodes_make[8];
   75.13 +        int scancodes_break[8];        
   75.14 +} scancode;
   75.15 +
   75.16 +static scancode scancode_set1[256] =
   75.17 +{
   75.18 +        { {-1},       {-1} },       { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
   75.19 +        { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
   75.20 +        { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
   75.21 +        { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
   75.22 +        { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
   75.23 +        { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
   75.24 +        { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
   75.25 +        { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
   75.26 +        { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
   75.27 +        { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
   75.28 +        { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
   75.29 +        { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
   75.30 +        { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
   75.31 +        { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
   75.32 +        { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
   75.33 +        { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
   75.34 +        { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
   75.35 +        { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
   75.36 +        { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
   75.37 +        { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
   75.38 +        { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
   75.39 +        { {0x54, -1}, {0xd4, -1} }, { {0x55, -1}, {0xd5, -1} }, { {0x56, -1}, {0xd6, -1} }, { {0x57, -1}, {0xd7, -1} },
   75.40 +        { {0x58, -1}, {0xd8, -1} }, { {0x59, -1}, {0xd9, -1} }, { {0x5a, -1}, {0xda, -1} }, { {0x5b, -1}, {0xdb, -1} },
   75.41 +        { {0x5c, -1}, {0xdc, -1} }, { {0x5d, -1}, {0xdd, -1} }, { {0x5e, -1}, {0xde, -1} }, { {0x5f, -1}, {0xdf, -1} },
   75.42 +        { {0x60, -1}, {0xe0, -1} }, { {0x61, -1}, {0xe1, -1} }, { {0x62, -1}, {0xe2, -1} }, { {0x63, -1}, {0xe3, -1} },
   75.43 +        { {0x64, -1}, {0xe4, -1} }, { {0x65, -1}, {0xe5, -1} }, { {0x66, -1}, {0xe6, -1} }, { {0x67, -1}, {0xe7, -1} },
   75.44 +        { {0x68, -1}, {0xe8, -1} }, { {0x69, -1}, {0xe9, -1} }, { {0x6a, -1}, {0xea, -1} }, { {0x6b, -1}, {0xeb, -1} },
   75.45 +        { {0x6c, -1}, {0xec, -1} }, { {0x6d, -1}, {0xed, -1} }, { {0x6e, -1}, {0xee, -1} }, { {0x6f, -1}, {0xef, -1} },
   75.46 +        { {0x70, -1}, {0xf0, -1} }, { {0x71, -1}, {0xf1, -1} }, { {0x72, -1}, {0xf2, -1} }, { {0x73, -1}, {0xf3, -1} },
   75.47 +        { {0x74, -1}, {0xf4, -1} }, { {0x75, -1}, {0xf5, -1} }, { {0x76, -1}, {0xf6, -1} }, { {0x77, -1}, {0xf7, -1} },
   75.48 +        { {0x78, -1}, {0xf8, -1} }, { {0x79, -1}, {0xf9, -1} }, { {0x7a, -1}, {0xfa, -1} }, { {0x7b, -1}, {0xfb, -1} },
   75.49 +        { {0x7c, -1}, {0xfc, -1} }, { {0x7d, -1}, {0xfd, -1} }, { {0x7e, -1}, {0xfe, -1} }, { {0x7f, -1}, {0xff, -1} },
   75.50 +
   75.51 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*80*/
   75.52 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*84*/
   75.53 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*88*/
   75.54 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*8c*/
   75.55 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*90*/
   75.56 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*94*/
   75.57 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*98*/
   75.58 +        { {0xe0, 0x1c, -1}, {0xe0, 0x9c, -1} }, { {0xe0, 0x1d, -1}, {0xe0, 0x9d, -1} }, { {-1},             {-1} },             { {-1},             {-1} },             /*9c*/
   75.59 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a0*/
   75.60 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a4*/
   75.61 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0xe0, 0x2a, -1}, {0xe0, 0x8a, -1} }, { {-1},             {-1} },             /*a8*/
   75.62 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ac*/
   75.63 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b0*/
   75.64 +        { {-1},             {-1} },             { {0xe0, 0x35, -1}, {0xe0, 0xb5, -1} }, { {0xe0, 0x36, -1}, {0xe0, 0xb6, -1} }, { {0xe0, 0x37, -1}, {0xe0, 0xb7, -1} }, /*b4*/
   75.65 +        { {0xe0, 0x38, -1}, {0xe0, 0xb8, -1} }, { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b8*/
   75.66 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*bc*/
   75.67 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*c0*/
   75.68 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0xe0, 0x46, -1}, {0xe0, 0xc6, -1} }, { {0xe0, 0x47, -1}, {0xe0, 0xc7, -1} }, /*c4*/
   75.69 +        { {0xe0, 0x48, -1}, {0xe0, 0xc8, -1} }, { {0xe0, 0x49, -1}, {0xe0, 0xc9, -1} }, { {-1},             {-1} },             { {0xe0, 0x4b, -1}, {0xe0, 0xcb, -1} }, /*c8*/
   75.70 +        { {-1},             {-1} },             { {0xe0, 0x4d, -1}, {0xe0, 0xcd, -1} }, { {-1},             {-1} },             { {0xe0, 0x4f, -1}, {0xe0, 0xcf, -1} }, /*cc*/
   75.71 +        { {0xe0, 0x50, -1}, {0xe0, 0xd0, -1} }, { {0xe0, 0x51, -1}, {0xe0, 0xd1, -1} }, { {0xe0, 0x52, -1}, {0xe0, 0xd2, -1} }, { {0xe0, 0x53, -1}, {0xe0, 0xd3, -1} }, /*d0*/
   75.72 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d4*/
   75.73 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d8*/
   75.74 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*dc*/
   75.75 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e0*/
   75.76 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e4*/
   75.77 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e8*/
   75.78 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ec*/
   75.79 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f0*/
   75.80 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f4*/
   75.81 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f8*/
   75.82 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5, -1},             {-1} }  /*fc*/
   75.83 +};
   75.84 +
   75.85 +/*XT keyboard has no escape scancodes, and no scancodes beyond 53*/
   75.86 +static scancode scancode_xt[256] =
   75.87 +{
   75.88 +        { {-1},       {-1} },       { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
   75.89 +        { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
   75.90 +        { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
   75.91 +        { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
   75.92 +        { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
   75.93 +        { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
   75.94 +        { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
   75.95 +        { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
   75.96 +        { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
   75.97 +        { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
   75.98 +        { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
   75.99 +        { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
  75.100 +        { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
  75.101 +        { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
  75.102 +        { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
  75.103 +        { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
  75.104 +        { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
  75.105 +        { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
  75.106 +        { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
  75.107 +        { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
  75.108 +        { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
  75.109 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*54*/
  75.110 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*58*/
  75.111 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*5c*/
  75.112 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*60*/
  75.113 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*64*/
  75.114 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*68*/
  75.115 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*6c*/
  75.116 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*70*/
  75.117 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*74*/
  75.118 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*78*/
  75.119 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*7c*/
  75.120 +
  75.121 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*80*/
  75.122 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*84*/
  75.123 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*88*/
  75.124 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*8c*/
  75.125 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*90*/
  75.126 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*94*/
  75.127 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*98*/
  75.128 +        { {0x1c, -1}, {0x9c, -1} },             { {0x1d, -1}, {0x9d, -1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*9c*/
  75.129 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a0*/
  75.130 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a4*/
  75.131 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0x2a, -1}, {0x8a, -1} },             { {-1},             {-1} },             /*a8*/
  75.132 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ac*/
  75.133 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b0*/
  75.134 +        { {-1},             {-1} },             { {0x35, -1}, {0xb5, -1} },             { {0x36, -1}, {0xb6, -1} },             { {0x37, -1}, {0xb7, -1} }, /*b4*/
  75.135 +        { {0x38, -1}, {0xb8, -1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b8*/
  75.136 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*bc*/
  75.137 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*c0*/
  75.138 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0x46, -1}, {0xc6, -1} },             { {0x47, -1}, {0xc7, -1} }, /*c4*/
  75.139 +        { {0x48, -1}, {0xc8, -1} },             { {0x49, -1}, {0xc9, -1} },             { {-1},             {-1} },             { {0x4b, -1}, {0xcb, -1} }, /*c8*/
  75.140 +        { {-1},             {-1} },             { {0x4d, -1}, {0xcd, -1} },             { {-1},             {-1} },             { {0x4f, -1}, {0xcf, -1} }, /*cc*/
  75.141 +        { {0x50, -1}, {0xd0, -1} },             { {0x51, -1}, {0xd1, -1} },             { {0x52, -1}, {0xd2, -1} },             { {0x53, -1}, {0xd3, -1} }, /*d0*/
  75.142 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d4*/
  75.143 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d8*/
  75.144 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*dc*/
  75.145 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e0*/
  75.146 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e4*/
  75.147 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e8*/
  75.148 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ec*/
  75.149 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f0*/
  75.150 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f4*/
  75.151 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f8*/
  75.152 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*fc*/
  75.153 +};
  75.154 +
  75.155 +/*Tandy keyboard has slightly different scancodes to XT*/
  75.156 +static scancode scancode_tandy[256] =
  75.157 +{
  75.158 +        { {-1},       {-1} },       { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
  75.159 +        { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
  75.160 +        { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
  75.161 +        { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
  75.162 +        { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
  75.163 +        { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
  75.164 +        { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
  75.165 +        { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
  75.166 +        { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
  75.167 +        { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
  75.168 +        { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x47, -1}, {0xc7, -1} },
  75.169 +        { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
  75.170 +        { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
  75.171 +        { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
  75.172 +        { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
  75.173 +        { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
  75.174 +        { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
  75.175 +        { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
  75.176 +        { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
  75.177 +        { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
  75.178 +        { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} },
  75.179 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*54*/
  75.180 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*58*/
  75.181 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*5c*/
  75.182 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*60*/
  75.183 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*64*/
  75.184 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*68*/
  75.185 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*6c*/
  75.186 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*70*/
  75.187 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*74*/
  75.188 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*78*/
  75.189 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*7c*/
  75.190 +
  75.191 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*80*/
  75.192 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*84*/
  75.193 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*88*/
  75.194 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*8c*/
  75.195 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*90*/
  75.196 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*94*/
  75.197 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*98*/
  75.198 +        { {0x57, -1}, {0xd7, -1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*9c*/
  75.199 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a0*/
  75.200 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*a4*/
  75.201 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0x2a, -1}, {0x8a, -1} },             { {-1},             {-1} },             /*a8*/
  75.202 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ac*/
  75.203 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b0*/
  75.204 +        { {-1},             {-1} },             { {0x35, -1}, {0xb5, -1} },             { {0x36, -1}, {0xb6, -1} },             { {0x37, -1}, {0xb7, -1} }, /*b4*/
  75.205 +        { {0x38, -1}, {0xb8, -1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*b8*/
  75.206 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*bc*/
  75.207 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*c0*/
  75.208 +        { {-1},             {-1} },             { {-1},             {-1} },             { {0x46, -1}, {0xc6, -1} },             { {0x47, -1}, {0xc7, -1} }, /*c4*/
  75.209 +        { {0x29, -1}, {0xa9, -1} },             { {0x49, -1}, {0xc9, -1} },             { {-1},             {-1} },             { {0x2b, -1}, {0xab, -1} }, /*c8*/
  75.210 +        { {-1},             {-1} },             { {0x4e, -1}, {0xce, -1} },             { {-1},             {-1} },             { {0x4f, -1}, {0xcf, -1} }, /*cc*/
  75.211 +        { {0x4a, -1}, {0xca, -1} },             { {0x51, -1}, {0xd1, -1} },             { {0x52, -1}, {0xd2, -1} },             { {0x53, -1}, {0xd3, -1} }, /*d0*/
  75.212 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d4*/
  75.213 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*d8*/
  75.214 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*dc*/
  75.215 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e0*/
  75.216 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e4*/
  75.217 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*e8*/
  75.218 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*ec*/
  75.219 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f0*/
  75.220 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f4*/
  75.221 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*f8*/
  75.222 +        { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             { {-1},             {-1} },             /*fc*/
  75.223 +};
  75.224 +static int oldkey[256];
  75.225 +static int keydelay[256];
  75.226 +
  75.227 +void (*keyboard_send)(uint8_t val);
  75.228 +void (*keyboard_poll)();
  75.229 +int keyboard_scan = 1;
  75.230 +
  75.231 +void keyboard_process()
  75.232 +{
  75.233 +        int c;
  75.234 +        int d;
  75.235 +        scancode *scancodes = (AT) ? scancode_set1 : scancode_xt;
  75.236 +        if (!keyboard_scan) return;
  75.237 +        if (TANDY) scancodes = scancode_tandy;
  75.238 +                
  75.239 +        for (c = 0; c < 256; c++)
  75.240 +        {
  75.241 +                if (key[c]) keydelay[c]++;
  75.242 +                else        keydelay[c] = 0;
  75.243 +        }
  75.244 +        
  75.245 +        for (c = 0; c < 256; c++)
  75.246 +        {
  75.247 +                if (key[c] != oldkey[c])
  75.248 +                {
  75.249 +                        oldkey[c] = key[c];
  75.250 +                        if ( key[c] && scancodes[c].scancodes_make[0]  == -1)
  75.251 +                           continue;
  75.252 +                        if (!key[c] && scancodes[c].scancodes_break[0] == -1)
  75.253 +                           continue;
  75.254 +                        pclog("Key %02X start\n", c);
  75.255 +                        d = 0;
  75.256 +                        if (key[c])
  75.257 +                        {
  75.258 +                                while (scancodes[c].scancodes_make[d] != -1)
  75.259 +                                      keyboard_send(scancodes[c].scancodes_make[d++]);
  75.260 +                        }
  75.261 +                        else
  75.262 +                        {
  75.263 +                                while (scancodes[c].scancodes_break[d] != -1)
  75.264 +                                      keyboard_send(scancodes[c].scancodes_break[d++]);
  75.265 +                        }
  75.266 +                }
  75.267 +        }
  75.268 +
  75.269 +        for (c = 0; c < 256; c++)
  75.270 +        {
  75.271 +                if (keydelay[c] >= 30)
  75.272 +                {
  75.273 +                        keydelay[c] -= 10;
  75.274 +                        if (scancode_set1[c].scancodes_make[0] == -1)
  75.275 +                           continue;
  75.276 +                           
  75.277 +                        d = 0;
  75.278 +
  75.279 +                        while (scancode_set1[c].scancodes_make[d] != -1)
  75.280 +                              keyboard_send(scancode_set1[c].scancodes_make[d++]);
  75.281 +                }
  75.282 +        }
  75.283 +}
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/src/keyboard.h	Sun Apr 21 14:54:35 2013 +0100
    76.3 @@ -0,0 +1,3 @@
    76.4 +extern void (*keyboard_send)(uint8_t val);
    76.5 +extern void (*keyboard_poll)();
    76.6 +extern int keyboard_scan;
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/src/keyboard_amstrad.c	Sun Apr 21 14:54:35 2013 +0100
    77.3 @@ -0,0 +1,168 @@
    77.4 +#include "ibm.h"
    77.5 +#include "io.h"
    77.6 +#include "mem.h"
    77.7 +#include "sound.h"
    77.8 +
    77.9 +#include "keyboard.h"
   77.10 +#include "keyboard_amstrad.h"
   77.11 +
   77.12 +#define STAT_PARITY     0x80
   77.13 +#define STAT_RTIMEOUT   0x40
   77.14 +#define STAT_TTIMEOUT   0x20
   77.15 +#define STAT_LOCK       0x10
   77.16 +#define STAT_CD         0x08
   77.17 +#define STAT_SYSFLAG    0x04
   77.18 +#define STAT_IFULL      0x02
   77.19 +#define STAT_OFULL      0x01
   77.20 +
   77.21 +struct
   77.22 +{
   77.23 +        int wantirq;
   77.24 +        
   77.25 +        uint8_t pa;        
   77.26 +        uint8_t pb;
   77.27 +} keyboard_amstrad;
   77.28 +
   77.29 +static uint8_t key_queue[16];
   77.30 +static int key_queue_start = 0, key_queue_end = 0;
   77.31 +
   77.32 +static uint8_t amstrad_systemstat_1, amstrad_systemstat_2;
   77.33 +
   77.34 +void keyboard_amstrad_poll()
   77.35 +{
   77.36 +        if (keyboard_amstrad.wantirq)
   77.37 +        {
   77.38 +                keyboard_amstrad.wantirq = 0;
   77.39 +                picint(2);
   77.40 +                pclog("keyboard_amstrad : take IRQ\n");
   77.41 +        }
   77.42 +        if (key_queue_start != key_queue_end)
   77.43 +        {
   77.44 +                keyboard_amstrad.pa = key_queue[key_queue_start];
   77.45 +                pclog("Reading %02X from the key queue at %i\n", keyboard_amstrad.pa, key_queue_start);
   77.46 +                key_queue_start = (key_queue_start + 1) & 0xf;
   77.47 +                keyboard_amstrad.wantirq = 1;        
   77.48 +        }                
   77.49 +}
   77.50 +
   77.51 +void keyboard_amstrad_adddata(uint8_t val)
   77.52 +{
   77.53 +        key_queue[key_queue_end] = val;
   77.54 +        pclog("keyboard_amstrad : %02X added to key queue at %i\n", val, key_queue_end);
   77.55 +        key_queue_end = (key_queue_end + 1) & 0xf;
   77.56 +        return;
   77.57 +}
   77.58 +
   77.59 +void keyboard_amstrad_write(uint16_t port, uint8_t val)
   77.60 +{
   77.61 +        pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, keyboard_amstrad.pb);
   77.62 +/*        if (ram[8] == 0xc3) 
   77.63 +        {
   77.64 +                output = 3;
   77.65 +        }*/
   77.66 +        switch (port)
   77.67 +        {
   77.68 +                case 0x61:
   77.69 +                pclog("keyboard_amstrad : pb write %02X %02X  %i %02X %i\n", val, keyboard_amstrad.pb, !(keyboard_amstrad.pb & 0x40), keyboard_amstrad.pb & 0x40, (val & 0x40));
   77.70 +                if (!(keyboard_amstrad.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/
   77.71 +                {
   77.72 +                        pclog("keyboard_amstrad : reset keyboard\n");
   77.73 +                        keyboard_amstrad_adddata(0xaa);
   77.74 +                }
   77.75 +                keyboard_amstrad.pb = val;
   77.76 +                ppi.pb = val;
   77.77 +
   77.78 +/*                if (AMSTRADIO) 
   77.79 +                   keyboard_amstrad.s2 = val & 4;
   77.80 +                else           
   77.81 +                   keyboard_amstrad.s2 = val & 8;*/
   77.82 +                gated = ((val & 3) == 3);
   77.83 +                if (gated) 
   77.84 +                   wasgated = 1;
   77.85 +                   
   77.86 +                if (val & 0x80)
   77.87 +                   keyboard_amstrad.pa = 0;
   77.88 +                break;
   77.89 +                
   77.90 +                case 0x63:
   77.91 +                break;
   77.92 +                
   77.93 +                case 0x64:
   77.94 +                amstrad_systemstat_1 = val;
   77.95 +                break;
   77.96 +                
   77.97 +                case 0x65:
   77.98 +                amstrad_systemstat_2 = val;
   77.99 +                break;
  77.100 +
  77.101 +                default:
  77.102 +                pclog("\nBad XT keyboard write %04X %02X\n", port, val);
  77.103 +//                dumpregs();
  77.104 +//                exit(-1);
  77.105 +        }
  77.106 +}
  77.107 +
  77.108 +uint8_t keyboard_amstrad_read(uint16_t port)
  77.109 +{
  77.110 +        uint8_t temp;
  77.111 +//        pclog("keyboard_amstrad : read %04X ", port);
  77.112 +        switch (port)
  77.113 +        {
  77.114 +                case 0x60:
  77.115 +                if (keyboard_amstrad.pb & 0x80)
  77.116 +                {
  77.117 +                        temp = (amstrad_systemstat_1 | 0xd) & 0x7f;
  77.118 +                }
  77.119 +                else
  77.120 +                {
  77.121 +                        temp = keyboard_amstrad.pa;
  77.122 +                        if (key_queue_start == key_queue_end)
  77.123 +                        {
  77.124 +                                keyboard_amstrad.wantirq = 0;
  77.125 +                        }
  77.126 +                        else
  77.127 +                        {
  77.128 +                                keyboard_amstrad.pa = key_queue[key_queue_start];
  77.129 +                                key_queue_start = (key_queue_start + 1) & 0xf;
  77.130 +                                keyboard_amstrad.wantirq = 1;        
  77.131 +                        }
  77.132 +                }        
  77.133 +                break;
  77.134 +                
  77.135 +                case 0x61:
  77.136 +                temp = keyboard_amstrad.pb;
  77.137 +                break;
  77.138 +                
  77.139 +                case 0x62:
  77.140 +                if (keyboard_amstrad.pb & 0x04)
  77.141 +                   temp = amstrad_systemstat_2 & 0xf;
  77.142 +                else
  77.143 +                   temp = amstrad_systemstat_2 >> 4;
  77.144 +                temp |= (ppispeakon ? 0x20 : 0);
  77.145 +                break;
  77.146 +                
  77.147 +                default:
  77.148 +                pclog("\nBad XT keyboard read %04X\n", port);
  77.149 +//                dumpregs();
  77.150 +//                exit(-1);
  77.151 +        }
  77.152 +//        pclog("%02X  %04X:%04X\n", temp, CS, pc);
  77.153 +        return temp;
  77.154 +}
  77.155 +
  77.156 +void keyboard_amstrad_reset()
  77.157 +{
  77.158 +        keyboard_amstrad.wantirq = 0;
  77.159 +        
  77.160 +        keyboard_scan = 1;
  77.161 +}
  77.162 +
  77.163 +void keyboard_amstrad_init()
  77.164 +{
  77.165 +        //return;
  77.166 +        pclog("keyboard_amstrad_init\n");
  77.167 +        io_sethandler(0x0060, 0x0006, keyboard_amstrad_read, NULL, NULL, keyboard_amstrad_write, NULL, NULL);
  77.168 +        keyboard_amstrad_reset();
  77.169 +        keyboard_send = keyboard_amstrad_adddata;
  77.170 +        keyboard_poll = keyboard_amstrad_poll;
  77.171 +}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/src/keyboard_amstrad.h	Sun Apr 21 14:54:35 2013 +0100
    78.3 @@ -0,0 +1,3 @@
    78.4 +void keyboard_amstrad_init();
    78.5 +void keyboard_amstrad_reset();
    78.6 +void keyboard_amstrad_poll();
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/src/keyboard_at.c	Sun Apr 21 14:54:35 2013 +0100
    79.3 @@ -0,0 +1,436 @@
    79.4 +#include "ibm.h"
    79.5 +#include "io.h"
    79.6 +#include "mem.h"
    79.7 +#include "sound.h"
    79.8 +
    79.9 +#include "keyboard.h"
   79.10 +#include "keyboard_at.h"
   79.11 +
   79.12 +#define STAT_PARITY     0x80
   79.13 +#define STAT_RTIMEOUT   0x40
   79.14 +#define STAT_TTIMEOUT   0x20
   79.15 +#define STAT_MFULL      0x20
   79.16 +#define STAT_LOCK       0x10
   79.17 +#define STAT_CD         0x08
   79.18 +#define STAT_SYSFLAG    0x04
   79.19 +#define STAT_IFULL      0x02
   79.20 +#define STAT_OFULL      0x01
   79.21 +
   79.22 +struct
   79.23 +{
   79.24 +        int initialised;
   79.25 +        int want60;
   79.26 +        int wantirq, wantirq12;
   79.27 +        uint8_t command;
   79.28 +        uint8_t status;
   79.29 +        uint8_t mem[0x20];
   79.30 +        uint8_t out;
   79.31 +        
   79.32 +        uint8_t input_port;
   79.33 +        uint8_t output_port;
   79.34 +        
   79.35 +        uint8_t key_command;
   79.36 +        int key_wantdata;
   79.37 +} keyboard_at;
   79.38 +
   79.39 +static uint8_t key_ctrl_queue[16];
   79.40 +static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0;
   79.41 +
   79.42 +static uint8_t key_queue[16];
   79.43 +static int key_queue_start = 0, key_queue_end = 0;
   79.44 +
   79.45 +static uint8_t mouse_queue[16];
   79.46 +int mouse_queue_start = 0, mouse_queue_end = 0;
   79.47 +
   79.48 +void keyboard_at_poll()
   79.49 +{
   79.50 +        if (keyboard_at.wantirq)
   79.51 +        {
   79.52 +                keyboard_at.wantirq = 0;
   79.53 +                picint(2);
   79.54 +                pclog("keyboard_at : take IRQ\n");
   79.55 +        }
   79.56 +        else if (keyboard_at.wantirq12)
   79.57 +        {
   79.58 +                keyboard_at.wantirq12 = 0;
   79.59 +                picint(0x1000);
   79.60 +                pclog("keyboard_at : take IRQ 12\n");
   79.61 +        }
   79.62 +        if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) &&
   79.63 +            mouse_queue_start != mouse_queue_end)
   79.64 +        {
   79.65 +                pclog("Reading %02X from the mouse queue at %i\n", keyboard_at.out, key_queue_start);
   79.66 +                keyboard_at.out = mouse_queue[mouse_queue_start];
   79.67 +                mouse_queue_start = (mouse_queue_start + 1) & 0xf;
   79.68 +                keyboard_at.status |=  STAT_OFULL | STAT_MFULL;
   79.69 +                keyboard_at.status &= ~STAT_IFULL;
   79.70 +                if (keyboard_at.mem[0] & 0x02)
   79.71 +                   keyboard_at.wantirq12 = 1;        
   79.72 +        }                
   79.73 +        else if (!(keyboard_at.status & STAT_OFULL) && !(keyboard_at.mem[0] & 0x10) &&
   79.74 +            key_queue_start != key_queue_end)
   79.75 +        {
   79.76 +                pclog("Reading %02X from the key queue at %i\n", keyboard_at.out, key_queue_start);
   79.77 +                keyboard_at.out = key_queue[key_queue_start];
   79.78 +                key_queue_start = (key_queue_start + 1) & 0xf;
   79.79 +                keyboard_at.status |=  STAT_OFULL;
   79.80 +                keyboard_at.status &= ~STAT_IFULL;
   79.81 +                if (keyboard_at.mem[0] & 0x01)
   79.82 +                   keyboard_at.wantirq = 1;        
   79.83 +        }                
   79.84 +        else if (!(keyboard_at.status & STAT_OFULL) && 
   79.85 +            key_ctrl_queue_start != key_ctrl_queue_end)
   79.86 +        {
   79.87 +                pclog("Reading %02X from the key ctrl_queue at %i\n", keyboard_at.out, key_ctrl_queue_start);
   79.88 +                keyboard_at.out = key_ctrl_queue[key_ctrl_queue_start];
   79.89 +                key_ctrl_queue_start = (key_ctrl_queue_start + 1) & 0xf;
   79.90 +                keyboard_at.status |=  STAT_OFULL;
   79.91 +                keyboard_at.status &= ~STAT_IFULL;
   79.92 +                if (keyboard_at.mem[0] & 0x01)
   79.93 +                   keyboard_at.wantirq = 1;        
   79.94 +        }                
   79.95 +}
   79.96 +
   79.97 +void keyboard_at_adddata(uint8_t val)
   79.98 +{
   79.99 +//        if (keyboard_at.status & STAT_OFULL)
  79.100 +//        {
  79.101 +                key_ctrl_queue[key_ctrl_queue_end] = val;
  79.102 +                key_ctrl_queue_end = (key_ctrl_queue_end + 1) & 0xf;
  79.103 +                pclog("keyboard_at : %02X added to queue\n", val);                
  79.104 +/*                return;
  79.105 +        }
  79.106 +        keyboard_at.out = val;
  79.107 +        keyboard_at.status |=  STAT_OFULL;
  79.108 +        keyboard_at.status &= ~STAT_IFULL;
  79.109 +        if (keyboard_at.mem[0] & 0x01)
  79.110 +           keyboard_at.wantirq = 1;        
  79.111 +        pclog("keyboard_at : output %02X (IRQ %i)\n", val, keyboard_at.wantirq);*/
  79.112 +}
  79.113 +
  79.114 +void keyboard_at_adddata_keyboard(uint8_t val)
  79.115 +{
  79.116 +        key_queue[key_queue_end] = val;
  79.117 +        key_queue_end = (key_queue_end + 1) & 0xf;
  79.118 +        pclog("keyboard_at : %02X added to key queue\n", val);
  79.119 +        return;
  79.120 +}
  79.121 +
  79.122 +void keyboard_at_adddata_mouse(uint8_t val)
  79.123 +{
  79.124 +        mouse_queue[mouse_queue_end] = val;
  79.125 +        mouse_queue_end = (mouse_queue_end + 1) & 0xf;
  79.126 +        pclog("keyboard_at : %02X added to mouse queue\n", val);
  79.127 +        return;
  79.128 +}
  79.129 +
  79.130 +void keyboard_at_write(uint16_t port, uint8_t val)
  79.131 +{
  79.132 +        pclog("keyboard_at : write %04X %02X %i  %02X\n", port, val, keyboard_at.key_wantdata, ram[8]);
  79.133 +/*        if (ram[8] == 0xc3) 
  79.134 +        {
  79.135 +                output = 3;
  79.136 +        }*/
  79.137 +        switch (port)
  79.138 +        {
  79.139 +                case 0x60:
  79.140 +                if (keyboard_at.want60)
  79.141 +                {
  79.142 +                        /*Write to controller*/
  79.143 +                        keyboard_at.want60 = 0;
  79.144 +                        switch (keyboard_at.command)
  79.145 +                        {
  79.146 +                                case 0x60: case 0x61: case 0x62: case 0x63:
  79.147 +                                case 0x64: case 0x65: case 0x66: case 0x67:
  79.148 +                                case 0x68: case 0x69: case 0x6a: case 0x6b:
  79.149 +                                case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  79.150 +                                case 0x70: case 0x71: case 0x72: case 0x73:
  79.151 +                                case 0x74: case 0x75: case 0x76: case 0x77:
  79.152 +                                case 0x78: case 0x79: case 0x7a: case 0x7b:
  79.153 +                                case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  79.154 +                                keyboard_at.mem[keyboard_at.command & 0x1f] = val;
  79.155 +                                if (keyboard_at.command == 0x60)
  79.156 +                                {
  79.157 +                                        if ((val & 1) && (keyboard_at.status & STAT_OFULL))
  79.158 +                                           keyboard_at.wantirq = 1;
  79.159 +                                        if (!(val & 1) && keyboard_at.wantirq)
  79.160 +                                           keyboard_at.wantirq = 0;
  79.161 +                                }                                           
  79.162 +                                break;
  79.163 +
  79.164 +                                case 0xcb: /*AMI - set keyboard mode*/
  79.165 +                                break;
  79.166 +                                
  79.167 +                                case 0xcf: /*??? - sent by MegaPC BIOS*/
  79.168 +                                break;
  79.169 +                                
  79.170 +                                case 0xd1: /*Write output port*/
  79.171 +                                pclog("Write output port - %02X %02X %04X:%04X\n", keyboard_at.output_port, val, CS, pc);
  79.172 +                                if ((keyboard_at.output_port ^ val) & 0x02) /*A20 enable change*/
  79.173 +                                {
  79.174 +                                        mem_a20_key = val & 0x02;
  79.175 +                                        mem_a20_recalc();
  79.176 +//                                        pclog("Rammask change to %08X %02X\n", rammask, val & 0x02);
  79.177 +                                        flushmmucache();
  79.178 +                                }
  79.179 +                                keyboard_at.output_port = val;
  79.180 +                                break;
  79.181 +                                
  79.182 +                                case 0xd3: /*Write to mouse output buffer*/
  79.183 +                                keyboard_at_adddata_mouse(val);
  79.184 +                                break;
  79.185 +                                
  79.186 +                                case 0xd4: /*Write to mouse*/
  79.187 +                                if (mouse_write)
  79.188 +                                   mouse_write(val);
  79.189 +                                break;     
  79.190 +                                
  79.191 +                                default:
  79.192 +                                pclog("Bad AT keyboard controller 0060 write %02X command %02X\n", val, keyboard_at.command);
  79.193 +//                                dumpregs();
  79.194 +//                                exit(-1);
  79.195 +                        }
  79.196 +                }
  79.197 +                else
  79.198 +                {
  79.199 +                        /*Write to keyboard*/                        
  79.200 +                        keyboard_at.mem[0] &= ~0x10;
  79.201 +                        if (keyboard_at.key_wantdata)
  79.202 +                        {
  79.203 +                                keyboard_at.key_wantdata = 0;
  79.204 +                                switch (keyboard_at.key_command)
  79.205 +                                {
  79.206 +                                        case 0xed: /*Set/reset LEDs*/
  79.207 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.208 +                                        break;
  79.209 +
  79.210 +                                        case 0xf3: /*Set typematic rate/delay*/
  79.211 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.212 +                                        break;
  79.213 +                                        
  79.214 +                                        default:
  79.215 +                                        pclog("Bad AT keyboard 0060 write %02X command %02X\n", val, keyboard_at.key_command);
  79.216 +//                                        dumpregs();
  79.217 +//                                        exit(-1);
  79.218 +                                }
  79.219 +                        }
  79.220 +                        else
  79.221 +                        {
  79.222 +                                keyboard_at.key_command = val;
  79.223 +                                switch (val)
  79.224 +                                {
  79.225 +                                        case 0x05: /*??? - sent by NT 4.0*/
  79.226 +                                        keyboard_at_adddata_keyboard(0xfe);
  79.227 +                                        break;
  79.228 +
  79.229 +                                        case 0xed: /*Set/reset LEDs*/
  79.230 +                                        keyboard_at.key_wantdata = 1;
  79.231 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.232 +                                        break;
  79.233 +                                        
  79.234 +                                        case 0xf2: /*Read ID*/
  79.235 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.236 +                                        keyboard_at_adddata_keyboard(0xab);
  79.237 +                                        keyboard_at_adddata_keyboard(0x41);
  79.238 +                                        break;
  79.239 +                                        
  79.240 +                                        case 0xf3: /*Set typematic rate/delay*/
  79.241 +                                        keyboard_at.key_wantdata = 1;
  79.242 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.243 +                                        break;
  79.244 +                                        
  79.245 +                                        case 0xf4: /*Enable keyboard*/
  79.246 +                                        keyboard_scan = 1;
  79.247 +                                        break;
  79.248 +                                        
  79.249 +                                        case 0xff: /*Reset*/
  79.250 +                                        keyboard_at_adddata_keyboard(0xfa);
  79.251 +                                        keyboard_at_adddata_keyboard(0xaa);
  79.252 +                                        break;
  79.253 +                                        
  79.254 +                                        default:
  79.255 +                                        pclog("Bad AT keyboard command %02X\n", val);
  79.256 +                                        keyboard_at_adddata_keyboard(0xfe);
  79.257 +//                                        dumpregs();
  79.258 +//                                        exit(-1);
  79.259 +                                }
  79.260 +                        }
  79.261 +                }
  79.262 +                break;
  79.263 +               
  79.264 +                case 0x61:
  79.265 +                ppi.pb=val;
  79.266 +                gated=((val&3)==3);
  79.267 +                if (gated) wasgated=1;                         
  79.268 +                break;
  79.269 +                
  79.270 +                case 0x64:
  79.271 +                keyboard_at.want60 = 0;
  79.272 +                keyboard_at.command = val;
  79.273 +                /*New controller command*/
  79.274 +                switch (val)
  79.275 +                {
  79.276 +                        case 0x20: case 0x21: case 0x22: case 0x23:
  79.277 +                        case 0x24: case 0x25: case 0x26: case 0x27:
  79.278 +                        case 0x28: case 0x29: case 0x2a: case 0x2b:
  79.279 +                        case 0x2c: case 0x2d: case 0x2e: case 0x2f:
  79.280 +                        case 0x30: case 0x31: case 0x32: case 0x33:
  79.281 +                        case 0x34: case 0x35: case 0x36: case 0x37:
  79.282 +                        case 0x38: case 0x39: case 0x3a: case 0x3b:
  79.283 +                        case 0x3c: case 0x3d: case 0x3e: case 0x3f:
  79.284 +                        keyboard_at_adddata(keyboard_at.mem[val & 0x1f]);
  79.285 +                        break;
  79.286 +
  79.287 +                        case 0x60: case 0x61: case 0x62: case 0x63:
  79.288 +                        case 0x64: case 0x65: case 0x66: case 0x67:
  79.289 +                        case 0x68: case 0x69: case 0x6a: case 0x6b:
  79.290 +                        case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  79.291 +                        case 0x70: case 0x71: case 0x72: case 0x73:
  79.292 +                        case 0x74: case 0x75: case 0x76: case 0x77:
  79.293 +                        case 0x78: case 0x79: case 0x7a: case 0x7b:
  79.294 +                        case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  79.295 +                        keyboard_at.want60 = 1;
  79.296 +                        break;
  79.297 +                        
  79.298 +                        case 0xa1: /*AMI - get controlled version*/
  79.299 +                        break;
  79.300 +                                
  79.301 +                        case 0xa7: /*Disable mouse port*/
  79.302 +                        break;
  79.303 +                        
  79.304 +                        case 0xa9: /*Test mouse port*/
  79.305 +                        keyboard_at_adddata(0x00); /*no error*/
  79.306 +                        break;
  79.307 +                        
  79.308 +                        case 0xaa: /*Self-test*/
  79.309 +                        if (!keyboard_at.initialised)
  79.310 +                        {
  79.311 +                                keyboard_at.initialised = 1;
  79.312 +                                key_ctrl_queue_start = key_ctrl_queue_end = 0;
  79.313 +                                keyboard_at.status &= ~STAT_OFULL;
  79.314 +                        }
  79.315 +                        keyboard_at.status |= STAT_SYSFLAG;
  79.316 +                        keyboard_at.mem[0] |= 0x04;
  79.317 +                        keyboard_at_adddata(0x55);
  79.318 +                        break;
  79.319 +                        
  79.320 +                        case 0xab: /*Interface test*/
  79.321 +                        keyboard_at_adddata(0x00); /*no error*/
  79.322 +                        break;
  79.323 +                        
  79.324 +                        case 0xad: /*Disable keyboard*/
  79.325 +                        keyboard_at.mem[0] |=  0x10;
  79.326 +                        break;
  79.327 +
  79.328 +                        case 0xae: /*Enable keyboard*/
  79.329 +                        keyboard_at.mem[0] &= ~0x10;
  79.330 +                        break;
  79.331 +                        
  79.332 +                        case 0xc0: /*Read input port*/
  79.333 +                        keyboard_at_adddata(keyboard_at.input_port);
  79.334 +                        keyboard_at.input_port = ((keyboard_at.input_port + 1) & 3) | (keyboard_at.input_port & 0xfc);
  79.335 +                        break;
  79.336 +                        
  79.337 +                        case 0xc9: /*AMI - block P22 and P23 ??? */
  79.338 +                        break;
  79.339 +                        
  79.340 +                        case 0xca: /*AMI - read keyboard mode*/
  79.341 +                        keyboard_at_adddata(0x00); /*ISA mode*/
  79.342 +                        break;
  79.343 +                        
  79.344 +                        case 0xcb: /*AMI - set keyboard mode*/
  79.345 +                        keyboard_at.want60 = 1;
  79.346 +                        break;
  79.347 +                        
  79.348 +                        case 0xcf: /*??? - sent by MegaPC BIOS*/
  79.349 +                        keyboard_at.want60 = 1;
  79.350 +                        break;
  79.351 +                        
  79.352 +                        case 0xd0: /*Read output port*/
  79.353 +                        keyboard_at_adddata(keyboard_at.output_port);
  79.354 +                        break;
  79.355 +                        
  79.356 +                        case 0xd1: /*Write output port*/
  79.357 +                        keyboard_at.want60 = 1;
  79.358 +                        break;
  79.359 +                        
  79.360 +                        case 0xd3: /*Write mouse output buffer*/
  79.361 +                        keyboard_at.want60 = 1;
  79.362 +                        break;
  79.363 +                        
  79.364 +                        case 0xd4: /*Write to mouse*/
  79.365 +                        keyboard_at.want60 = 1;
  79.366 +                        break;
  79.367 +                        
  79.368 +                        case 0xe0: /*Read test inputs*/
  79.369 +                        keyboard_at_adddata(0x00);
  79.370 +                        break;
  79.371 +                        
  79.372 +                        case 0xef: /*??? - sent by AMI486*/
  79.373 +                        break;
  79.374 +                        
  79.375 +                        case 0xfe: /*Pulse output port - pin 0 selected - x86 reset*/
  79.376 +                        softresetx86(); /*Pulse reset!*/
  79.377 +                        break;
  79.378 +                                                
  79.379 +                        case 0xff: /*Pulse output port - but no pins selected - sent by MegaPC BIOS*/
  79.380 +                        break;
  79.381 +                                
  79.382 +                        default:
  79.383 +                        pclog("Bad AT keyboard controller command %02X\n", val);
  79.384 +//                        dumpregs();
  79.385 +//                        exit(-1);
  79.386 +                }
  79.387 +        }
  79.388 +}
  79.389 +
  79.390 +uint8_t keyboard_at_read(uint16_t port)
  79.391 +{
  79.392 +        uint8_t temp = 0xff;
  79.393 +        cycles -= 4;
  79.394 +//        if (port != 0x61) pclog("keyboard_at : read %04X ", port);
  79.395 +        switch (port)
  79.396 +        {
  79.397 +                case 0x60:
  79.398 +                temp = keyboard_at.out;
  79.399 +                keyboard_at.status &= ~(STAT_OFULL | STAT_MFULL);
  79.400 +                keyboard_at.wantirq = keyboard_at.wantirq12 = 0;
  79.401 +                break;
  79.402 +
  79.403 +                case 0x61:                
  79.404 +                if (ppispeakon) return (ppi.pb&~0xC0)|0x20;
  79.405 +                return ppi.pb&~0xC0;
  79.406 +                break;
  79.407 +                
  79.408 +                case 0x64:
  79.409 +                temp = keyboard_at.status;
  79.410 +                keyboard_at.status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT);
  79.411 +                break;
  79.412 +        }
  79.413 +//        if (port != 0x61) pclog("%02X  %08X\n", temp, rammask);
  79.414 +        return temp;
  79.415 +}
  79.416 +
  79.417 +void keyboard_at_reset()
  79.418 +{
  79.419 +        keyboard_at.initialised = 0;
  79.420 +        keyboard_at.status = STAT_LOCK | STAT_CD;
  79.421 +        keyboard_at.mem[0] = 0x11;
  79.422 +        keyboard_at.wantirq = 0;
  79.423 +        keyboard_at.output_port = 0;
  79.424 +        keyboard_at.input_port = 0xb0;
  79.425 +        
  79.426 +        keyboard_at.key_wantdata = 0;
  79.427 +        
  79.428 +        keyboard_scan = 1;
  79.429 +}
  79.430 +
  79.431 +void keyboard_at_init()
  79.432 +{
  79.433 +        //return;
  79.434 +        io_sethandler(0x0060, 0x0005, keyboard_at_read, NULL, NULL, keyboard_at_write, NULL, NULL);
  79.435 +        keyboard_at_reset();
  79.436 +        keyboard_send = keyboard_at_adddata_keyboard;
  79.437 +        keyboard_poll = keyboard_at_poll;
  79.438 +        mouse_write = NULL;
  79.439 +}
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/src/keyboard_at.h	Sun Apr 21 14:54:35 2013 +0100
    80.3 @@ -0,0 +1,6 @@
    80.4 +void keyboard_at_init();
    80.5 +void keyboard_at_reset();
    80.6 +void keyboard_at_poll();
    80.7 +
    80.8 +void (*mouse_write)(uint8_t val);
    80.9 +extern int mouse_queue_start, mouse_queue_end;
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/src/keyboard_olim24.c	Sun Apr 21 14:54:35 2013 +0100
    81.3 @@ -0,0 +1,285 @@
    81.4 +#include "ibm.h"
    81.5 +#include "io.h"
    81.6 +#include "mem.h"
    81.7 +#include "mouse.h"
    81.8 +
    81.9 +#include "keyboard.h"
   81.10 +#include "keyboard_olim24.h"
   81.11 +
   81.12 +#define STAT_PARITY     0x80
   81.13 +#define STAT_RTIMEOUT   0x40
   81.14 +#define STAT_TTIMEOUT   0x20
   81.15 +#define STAT_LOCK       0x10
   81.16 +#define STAT_CD         0x08
   81.17 +#define STAT_SYSFLAG    0x04
   81.18 +#define STAT_IFULL      0x02
   81.19 +#define STAT_OFULL      0x01
   81.20 +
   81.21 +struct
   81.22 +{
   81.23 +        int wantirq;
   81.24 +        uint8_t command;
   81.25 +        uint8_t status;
   81.26 +        uint8_t out;
   81.27 +        
   81.28 +        uint8_t output_port;
   81.29 +
   81.30 +        int param, param_total;
   81.31 +        uint8_t params[16];
   81.32 +        
   81.33 +        int mouse_mode;
   81.34 +} keyboard_olim24;
   81.35 +
   81.36 +static uint8_t key_queue[16];
   81.37 +static int key_queue_start = 0, key_queue_end = 0;
   81.38 +
   81.39 +static uint8_t mouse_scancodes[7];
   81.40 +
   81.41 +void keyboard_olim24_poll()
   81.42 +{
   81.43 +        //pclog("poll %i\n", keyboard_olim24.wantirq);
   81.44 +        if (keyboard_olim24.wantirq)
   81.45 +        {
   81.46 +                keyboard_olim24.wantirq = 0;
   81.47 +                picint(2);
   81.48 +                pclog("keyboard_olim24 : take IRQ\n");
   81.49 +        }
   81.50 +        if (!(keyboard_olim24.status & STAT_OFULL) && key_queue_start != key_queue_end)
   81.51 +        {
   81.52 +                pclog("Reading %02X from the key queue at %i\n", keyboard_olim24.out, key_queue_start);
   81.53 +                keyboard_olim24.out = key_queue[key_queue_start];
   81.54 +                key_queue_start = (key_queue_start + 1) & 0xf;
   81.55 +                keyboard_olim24.status |=  STAT_OFULL;
   81.56 +                keyboard_olim24.status &= ~STAT_IFULL;
   81.57 +                keyboard_olim24.wantirq = 1;        
   81.58 +        }                
   81.59 +}
   81.60 +
   81.61 +void keyboard_olim24_adddata(uint8_t val)
   81.62 +{
   81.63 +        key_queue[key_queue_end] = val;
   81.64 +        key_queue_end = (key_queue_end + 1) & 0xf;
   81.65 +        pclog("keyboard_olim24 : %02X added to key queue %02X\n", val, keyboard_olim24.status);
   81.66 +        return;
   81.67 +}
   81.68 +
   81.69 +void keyboard_olim24_write(uint16_t port, uint8_t val)
   81.70 +{
   81.71 +        pclog("keyboard_olim24 : write %04X %02X\n", port, val);
   81.72 +/*        if (ram[8] == 0xc3) 
   81.73 +        {
   81.74 +                output = 3;
   81.75 +        }*/
   81.76 +        switch (port)
   81.77 +        {
   81.78 +                case 0x60:
   81.79 +                if (keyboard_olim24.param != keyboard_olim24.param_total)
   81.80 +                {
   81.81 +                        keyboard_olim24.params[keyboard_olim24.param++] = val;
   81.82 +                        if (keyboard_olim24.param == keyboard_olim24.param_total)
   81.83 +                        {
   81.84 +                                switch (keyboard_olim24.command)
   81.85 +                                {
   81.86 +                                        case 0x11:
   81.87 +                                        keyboard_olim24.mouse_mode = 0;
   81.88 +                                        mouse_scancodes[0] = keyboard_olim24.params[0];
   81.89 +                                        mouse_scancodes[1] = keyboard_olim24.params[1];
   81.90 +                                        mouse_scancodes[2] = keyboard_olim24.params[2];
   81.91 +                                        mouse_scancodes[3] = keyboard_olim24.params[3];
   81.92 +                                        mouse_scancodes[4] = keyboard_olim24.params[4];
   81.93 +                                        mouse_scancodes[5] = keyboard_olim24.params[5];
   81.94 +                                        mouse_scancodes[6] = keyboard_olim24.params[6];
   81.95 +                                        break;
   81.96 +
   81.97 +                                        case 0x12:
   81.98 +                                        keyboard_olim24.mouse_mode = 1;
   81.99 +                                        mouse_scancodes[0] = keyboard_olim24.params[0];
  81.100 +                                        mouse_scancodes[1] = keyboard_olim24.params[1];
  81.101 +                                        mouse_scancodes[2] = keyboard_olim24.params[2];
  81.102 +                                        break;
  81.103 +                                        
  81.104 +                                        default:
  81.105 +                                        pclog("Bad keyboard command complete %02X\n", keyboard_olim24.command);
  81.106 +//                                        dumpregs();
  81.107 +//                                        exit(-1);
  81.108 +                                }
  81.109 +                        }
  81.110 +                }
  81.111 +                else
  81.112 +                {
  81.113 +                        keyboard_olim24.command = val;
  81.114 +                        switch (val)
  81.115 +                        {
  81.116 +                                case 0x01: /*Self-test*/
  81.117 +                                break;
  81.118 +                                
  81.119 +                                case 0x05: /*Read ID*/
  81.120 +                                keyboard_olim24_adddata(0x00);
  81.121 +                                break;
  81.122 +                                
  81.123 +                                case 0x11:
  81.124 +                                keyboard_olim24.param = 0;
  81.125 +                                keyboard_olim24.param_total = 9;
  81.126 +                                break;
  81.127 +                                
  81.128 +                                case 0x12:
  81.129 +                                keyboard_olim24.param = 0;
  81.130 +                                keyboard_olim24.param_total = 4;
  81.131 +                                break;
  81.132 +                                
  81.133 +                                default:
  81.134 +                                pclog("Bad keyboard command %02X\n", val);
  81.135 +//                                dumpregs();
  81.136 +//                                exit(-1);
  81.137 +                        }
  81.138 +                }
  81.139 +                        
  81.140 +                break;                
  81.141 +        }
  81.142 +}
  81.143 +
  81.144 +uint8_t keyboard_olim24_read(uint16_t port)
  81.145 +{
  81.146 +        uint8_t temp;
  81.147 +//        pclog("keyboard_olim24 : read %04X ", port);
  81.148 +        switch (port)
  81.149 +        {
  81.150 +                case 0x60:
  81.151 +                temp = keyboard_olim24.out;
  81.152 +                if (key_queue_start == key_queue_end)
  81.153 +                {
  81.154 +                        keyboard_olim24.status &= ~STAT_OFULL;
  81.155 +                        keyboard_olim24.wantirq = 0;
  81.156 +                }
  81.157 +                else
  81.158 +                {
  81.159 +                        keyboard_olim24.out = key_queue[key_queue_start];
  81.160 +                        key_queue_start = (key_queue_start + 1) & 0xf;
  81.161 +                        keyboard_olim24.status |=  STAT_OFULL;
  81.162 +                        keyboard_olim24.status &= ~STAT_IFULL;
  81.163 +                        keyboard_olim24.wantirq = 1;        
  81.164 +                }        
  81.165 +                break;
  81.166 +                
  81.167 +                case 0x64:
  81.168 +                temp = keyboard_olim24.status;
  81.169 +                keyboard_olim24.status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT);
  81.170 +                break;
  81.171 +                
  81.172 +                default:
  81.173 +                pclog("\nBad olim24 keyboard read %04X\n", port);
  81.174 +//                dumpregs();
  81.175 +//                exit(-1);
  81.176 +        }
  81.177 +//        pclog("%02X\n", temp);
  81.178 +        return temp;
  81.179 +}
  81.180 +
  81.181 +void keyboard_olim24_reset()
  81.182 +{
  81.183 +        keyboard_olim24.status = STAT_LOCK | STAT_CD;
  81.184 +        keyboard_olim24.wantirq = 0;
  81.185 +        
  81.186 +        keyboard_scan = 1;
  81.187 +        
  81.188 +        keyboard_olim24.param = keyboard_olim24.param_total = 0;
  81.189 +        
  81.190 +        keyboard_olim24.mouse_mode = 0;
  81.191 +        mouse_scancodes[0] = 0x1c;
  81.192 +        mouse_scancodes[1] = 0x53;
  81.193 +        mouse_scancodes[2] = 0x01;
  81.194 +        mouse_scancodes[3] = 0x4b;
  81.195 +        mouse_scancodes[4] = 0x4d;
  81.196 +        mouse_scancodes[5] = 0x48;
  81.197 +        mouse_scancodes[6] = 0x50;
  81.198 +}
  81.199 +
  81.200 +static int mouse_x = 0, mouse_y = 0, mouse_b = 0;
  81.201 +void mouse_olim24_poll(int x, int y, int b)
  81.202 +{
  81.203 +        mouse_x += x;
  81.204 +        mouse_y += y;
  81.205 +
  81.206 +        pclog("mouse_poll - %i, %i  %i, %i\n", x, y, mouse_x, mouse_y);
  81.207 +        
  81.208 +        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.209 +        if ((b & 1) && !(mouse_b & 1))
  81.210 +           keyboard_olim24_adddata(mouse_scancodes[0]);
  81.211 +        if (!(b & 1) && (mouse_b & 1))
  81.212 +           keyboard_olim24_adddata(mouse_scancodes[0] | 0x80);
  81.213 +        mouse_b = (mouse_b & ~1) | (b & 1);
  81.214 +        
  81.215 +        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.216 +        if ((b & 2) && !(mouse_b & 2))
  81.217 +           keyboard_olim24_adddata(mouse_scancodes[2]);
  81.218 +        if (!(b & 2) && (mouse_b & 2))
  81.219 +           keyboard_olim24_adddata(mouse_scancodes[2] | 0x80);
  81.220 +        mouse_b = (mouse_b & ~2) | (b & 2);
  81.221 +        
  81.222 +        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.223 +        if ((b & 4) && !(mouse_b & 4))
  81.224 +           keyboard_olim24_adddata(mouse_scancodes[1]);
  81.225 +        if (!(b & 4) && (mouse_b & 4))
  81.226 +           keyboard_olim24_adddata(mouse_scancodes[1] | 0x80);
  81.227 +        mouse_b = (mouse_b & ~4) | (b & 4);
  81.228 +        
  81.229 +        if (keyboard_olim24.mouse_mode)
  81.230 +        {
  81.231 +                if (((key_queue_end - key_queue_start) & 0xf) > 12) return;
  81.232 +                if (!mouse_x && !mouse_y) return;
  81.233 +                
  81.234 +                mouse_y = -mouse_y;
  81.235 +                
  81.236 +                if (mouse_x < -127) mouse_x = -127;
  81.237 +                if (mouse_x >  127) mouse_x =  127;
  81.238 +                if (mouse_x < -127) mouse_x = 0x80 | ((-mouse_x) & 0x7f);
  81.239 +
  81.240 +                if (mouse_y < -127) mouse_y = -127;
  81.241 +                if (mouse_y >  127) mouse_y =  127;
  81.242 +                if (mouse_y < -127) mouse_y = 0x80 | ((-mouse_y) & 0x7f);
  81.243 +                
  81.244 +                keyboard_olim24_adddata(0xfe);
  81.245 +                keyboard_olim24_adddata(mouse_x);
  81.246 +                keyboard_olim24_adddata(mouse_y);
  81.247 +                
  81.248 +                mouse_x = mouse_y = 0;
  81.249 +        }
  81.250 +        else
  81.251 +        {   
  81.252 +                while (mouse_x < -4)
  81.253 +                {
  81.254 +                        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.255 +                        mouse_x+=4;
  81.256 +                        keyboard_olim24_adddata(mouse_scancodes[3]);
  81.257 +                }
  81.258 +                while (mouse_x > 4)
  81.259 +                {
  81.260 +                        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.261 +                        mouse_x-=4;
  81.262 +                        keyboard_olim24_adddata(mouse_scancodes[4]);
  81.263 +                }
  81.264 +                while (mouse_y < -4)
  81.265 +                {
  81.266 +                        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.267 +                        mouse_y+=4;
  81.268 +                        keyboard_olim24_adddata(mouse_scancodes[5]);
  81.269 +                }
  81.270 +                while (mouse_y > 4)
  81.271 +                {
  81.272 +                        if (((key_queue_end - key_queue_start) & 0xf) > 14) return;
  81.273 +                        mouse_y-=4;
  81.274 +                        keyboard_olim24_adddata(mouse_scancodes[6]);
  81.275 +                }
  81.276 +        }
  81.277 +}
  81.278 +
  81.279 +void keyboard_olim24_init()
  81.280 +{
  81.281 +        //return;
  81.282 +        io_sethandler(0x0060, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL);
  81.283 +        io_sethandler(0x0064, 0x0001, keyboard_olim24_read, NULL, NULL, keyboard_olim24_write, NULL, NULL);
  81.284 +        keyboard_olim24_reset();
  81.285 +        keyboard_send = keyboard_olim24_adddata;
  81.286 +        keyboard_poll = keyboard_olim24_poll;
  81.287 +        mouse_poll    = mouse_olim24_poll;
  81.288 +}
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/src/keyboard_olim24.h	Sun Apr 21 14:54:35 2013 +0100
    82.3 @@ -0,0 +1,3 @@
    82.4 +void keyboard_olim24_init();
    82.5 +void keyboard_olim24_reset();
    82.6 +void keyboard_olim24_poll();
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/src/keyboard_xt.c	Sun Apr 21 14:54:35 2013 +0100
    83.3 @@ -0,0 +1,163 @@
    83.4 +#include "ibm.h"
    83.5 +#include "io.h"
    83.6 +#include "mem.h"
    83.7 +#include "sound.h"
    83.8 +
    83.9 +#include "keyboard.h"
   83.10 +#include "keyboard_xt.h"
   83.11 +
   83.12 +#define STAT_PARITY     0x80
   83.13 +#define STAT_RTIMEOUT   0x40
   83.14 +#define STAT_TTIMEOUT   0x20
   83.15 +#define STAT_LOCK       0x10
   83.16 +#define STAT_CD         0x08
   83.17 +#define STAT_SYSFLAG    0x04
   83.18 +#define STAT_IFULL      0x02
   83.19 +#define STAT_OFULL      0x01
   83.20 +
   83.21 +struct
   83.22 +{
   83.23 +        int wantirq;
   83.24 +        
   83.25 +        uint8_t pa;        
   83.26 +        uint8_t pb;
   83.27 +} keyboard_xt;
   83.28 +
   83.29 +static uint8_t key_queue[16];
   83.30 +static int key_queue_start = 0, key_queue_end = 0;
   83.31 +
   83.32 +void keyboard_xt_poll()
   83.33 +{
   83.34 +        if (keyboard_xt.wantirq)
   83.35 +        {
   83.36 +                keyboard_xt.wantirq = 0;
   83.37 +                picint(2);
   83.38 +                pclog("keyboard_xt : take IRQ\n");
   83.39 +        }
   83.40 +        if (key_queue_start != key_queue_end)
   83.41 +        {
   83.42 +                keyboard_xt.pa = key_queue[key_queue_start];
   83.43 +                pclog("Reading %02X from the key queue at %i\n", keyboard_xt.pa, key_queue_start);
   83.44 +                key_queue_start = (key_queue_start + 1) & 0xf;
   83.45 +                keyboard_xt.wantirq = 1;        
   83.46 +        }                
   83.47 +}
   83.48 +
   83.49 +void keyboard_xt_adddata(uint8_t val)
   83.50 +{
   83.51 +        key_queue[key_queue_end] = val;
   83.52 +        pclog("keyboard_xt : %02X added to key queue at %i\n", val, key_queue_end);
   83.53 +        key_queue_end = (key_queue_end + 1) & 0xf;
   83.54 +        return;
   83.55 +}
   83.56 +
   83.57 +void keyboard_xt_write(uint16_t port, uint8_t val)
   83.58 +{
   83.59 +        pclog("keyboard_xt : write %04X %02X %02X\n", port, val, keyboard_xt.pb);
   83.60 +/*        if (ram[8] == 0xc3) 
   83.61 +        {
   83.62 +                output = 3;
   83.63 +        }*/
   83.64 +        switch (port)
   83.65 +        {
   83.66 +                case 0x61:
   83.67 +                pclog("keyboard_xt : pb write %02X %02X  %i %02X %i\n", val, keyboard_xt.pb, !(keyboard_xt.pb & 0x40), keyboard_xt.pb & 0x40, (val & 0x40));
   83.68 +                if (!(keyboard_xt.pb & 0x40) && (val & 0x40)) /*Reset keyboard*/
   83.69 +                {
   83.70 +                        pclog("keyboard_xt : reset keyboard\n");
   83.71 +                        keyboard_xt_adddata(0xaa);
   83.72 +                }
   83.73 +                keyboard_xt.pb = val;
   83.74 +                ppi.pb = val;
   83.75 +/*                if (AMSTRADIO) 
   83.76 +                   keyboard_xt.s2 = val & 4;
   83.77 +                else           
   83.78 +                   keyboard_xt.s2 = val & 8;*/
   83.79 +                gated = ((val & 3) == 3);
   83.80 +                if (gated) 
   83.81 +                   wasgated = 1;
   83.82 +                   
   83.83 +                if (val & 0x80)
   83.84 +                {
   83.85 +                        keyboard_xt.pa = 0;
   83.86 +                        picintc(2);
   83.87 +                }
   83.88 +                break;
   83.89 +        }
   83.90 +}
   83.91 +
   83.92 +uint8_t keyboard_xt_read(uint16_t port)
   83.93 +{
   83.94 +        uint8_t temp;
   83.95 +//        pclog("keyboard_xt : read %04X ", port);
   83.96 +        switch (port)
   83.97 +        {
   83.98 +                case 0x60:
   83.99 +                if (keyboard_xt.pb & 0x80)
  83.100 +                {
  83.101 +                        if (VGA) 
  83.102 +                           temp = 0x4D;
  83.103 +                        else if (MDA) 
  83.104 +                           temp = 0x7D;
  83.105 +                        else            
  83.106 +                           temp = 0x6D;
  83.107 +                }
  83.108 +                else
  83.109 +                {
  83.110 +                        temp = keyboard_xt.pa;
  83.111 +                        if (key_queue_start == key_queue_end)
  83.112 +                        {
  83.113 +                                keyboard_xt.wantirq = 0;
  83.114 +                        }
  83.115 +                        else
  83.116 +                        {
  83.117 +                                keyboard_xt.pa = key_queue[key_queue_start];
  83.118 +                                key_queue_start = (key_queue_start + 1) & 0xf;
  83.119 +                                keyboard_xt.wantirq = 1;        
  83.120 +                        }
  83.121 +                }        
  83.122 +                break;
  83.123 +                
  83.124 +                case 0x61:
  83.125 +                temp = keyboard_xt.pb;
  83.126 +                break;
  83.127 +                
  83.128 +                case 0x62:
  83.129 +                if (keyboard_xt.pb & 0x08)
  83.130 +                {
  83.131 +                        if (VGA) 
  83.132 +                           temp = 4;
  83.133 +                        else if (MDA)
  83.134 +                           temp = 7;
  83.135 +                        else
  83.136 +                           temp = 6;
  83.137 +                }
  83.138 +                else
  83.139 +                   temp = 0xD;
  83.140 +                temp |= (ppispeakon ? 0x20 : 0);
  83.141 +                break;
  83.142 +                
  83.143 +                default:
  83.144 +                pclog("\nBad XT keyboard read %04X\n", port);
  83.145 +                //dumpregs();
  83.146 +                //exit(-1);
  83.147 +        }
  83.148 +//        pclog("%02X\n", temp);
  83.149 +        return temp;
  83.150 +}
  83.151 +
  83.152 +void keyboard_xt_reset()
  83.153 +{
  83.154 +        keyboard_xt.wantirq = 0;
  83.155 +        
  83.156 +        keyboard_scan = 1;
  83.157 +}
  83.158 +
  83.159 +void keyboard_xt_init()
  83.160 +{
  83.161 +        //return;
  83.162 +        io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL);
  83.163 +        keyboard_xt_reset();
  83.164 +        keyboard_send = keyboard_xt_adddata;
  83.165 +        keyboard_poll = keyboard_xt_poll;
  83.166 +}
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/src/keyboard_xt.h	Sun Apr 21 14:54:35 2013 +0100
    84.3 @@ -0,0 +1,3 @@
    84.4 +void keyboard_xt_init();
    84.5 +void keyboard_xt_reset();
    84.6 +void keyboard_xt_poll();
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/src/lpt.c	Sun Apr 21 14:54:35 2013 +0100
    85.3 @@ -0,0 +1,66 @@
    85.4 +#include "ibm.h"
    85.5 +#include "io.h"
    85.6 +
    85.7 +#include "lpt.h"
    85.8 +
    85.9 +static uint8_t lpt1_dat, lpt2_dat;
   85.10 +void lpt1_write(uint16_t port, uint8_t val)
   85.11 +{
   85.12 +        switch (port & 3)
   85.13 +        {
   85.14 +                case 0:
   85.15 +                writedac(val);
   85.16 +                lpt1_dat = val;
   85.17 +                break;
   85.18 +                case 2:
   85.19 +                writedacctrl(val);
   85.20 +                break;
   85.21 +        }
   85.22 +}
   85.23 +uint8_t lpt1_read(uint16_t port)
   85.24 +{
   85.25 +        switch (port & 3)
   85.26 +        {
   85.27 +                case 0:
   85.28 +                return lpt1_dat;
   85.29 +                case 1:
   85.30 +                return readdacfifo();
   85.31 +        }
   85.32 +        return 0xff;
   85.33 +}
   85.34 +
   85.35 +void lpt2_write(uint16_t port, uint8_t val)
   85.36 +{
   85.37 +        switch (port & 3)
   85.38 +        {
   85.39 +                case 0:
   85.40 +                writedac(val);
   85.41 +                lpt2_dat = val;
   85.42 +                break;
   85.43 +                case 2:
   85.44 +                writedacctrl(val);
   85.45 +                break;
   85.46 +        }
   85.47 +}
   85.48 +uint8_t lpt2_read(uint16_t port)
   85.49 +{
   85.50 +        switch (port & 3)
   85.51 +        {
   85.52 +                case 0:
   85.53 +                return lpt2_dat;
   85.54 +                case 1:
   85.55 +                return readdacfifo();
   85.56 +        }
   85.57 +        return 0xff;
   85.58 +}
   85.59 +
   85.60 +void lpt_init()
   85.61 +{
   85.62 +        io_sethandler(0x0278, 0x0003, lpt1_read, NULL, NULL, lpt1_write, NULL, NULL);
   85.63 +        io_sethandler(0x0378, 0x0003, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL);
   85.64 +}
   85.65 +
   85.66 +void lpt2_remove()
   85.67 +{
   85.68 +        io_removehandler(0x0379, 0x0002, lpt2_read, NULL, NULL, lpt2_write, NULL, NULL);
   85.69 +}
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/src/lpt.h	Sun Apr 21 14:54:35 2013 +0100
    86.3 @@ -0,0 +1,2 @@
    86.4 +void lpt_init();
    86.5 +void lpt2_remove();
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/src/mame/fmopl.c	Sun Apr 21 14:54:35 2013 +0100
    87.3 @@ -0,0 +1,2613 @@
    87.4 +/*
    87.5 +**
    87.6 +** File: fmopl.c - software implementation of FM sound generator
    87.7 +**                                            types OPL and OPL2
    87.8 +**
    87.9 +** Copyright Jarek Burczynski (bujar at mame dot net)
   87.10 +** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development
   87.11 +**
   87.12 +** Version 0.72
   87.13 +**
   87.14 +
   87.15 +Revision History:
   87.16 +
   87.17 +04-08-2003 Jarek Burczynski:
   87.18 + - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip
   87.19 +   handles memory read/write or during the adpcm synthesis when the chip
   87.20 +   requests another byte of ADPCM data.
   87.21 +
   87.22 +24-07-2003 Jarek Burczynski:
   87.23 + - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after
   87.24 +   some (unknown) delay). Right now it's always set.
   87.25 +
   87.26 +14-06-2003 Jarek Burczynski:
   87.27 + - implemented all of the status register flags in Y8950 emulation
   87.28 + - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since
   87.29 +   they can be either RAM or ROM
   87.30 +
   87.31 +08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip)
   87.32 + - corrected ym3526_read() to always set bit 2 and bit 1
   87.33 +   to HIGH state - identical to ym3812_read (verified on real YM3526)
   87.34 +
   87.35 +04-28-2002 Jarek Burczynski:
   87.36 + - binary exact Envelope Generator (verified on real YM3812);
   87.37 +   compared to YM2151: the EG clock is equal to internal_clock,
   87.38 +   rates are 2 times slower and volume resolution is one bit less
   87.39 + - modified interface functions (they no longer return pointer -
   87.40 +   that's internal to the emulator now):
   87.41 +    - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init()
   87.42 + - corrected 'off by one' error in feedback calculations (when feedback is off)
   87.43 + - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)
   87.44 + - speeded up noise generator calculations (Nicola Salmoria)
   87.45 +
   87.46 +03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)
   87.47 + Complete rewrite (all verified on real YM3812):
   87.48 + - corrected sin_tab and tl_tab data
   87.49 + - corrected operator output calculations
   87.50 + - corrected waveform_select_enable register;
   87.51 +   simply: ignore all writes to waveform_select register when
   87.52 +   waveform_select_enable == 0 and do not change the waveform previously selected.
   87.53 + - corrected KSR handling
   87.54 + - corrected Envelope Generator: attack shape, Sustain mode and
   87.55 +   Percussive/Non-percussive modes handling
   87.56 + - Envelope Generator rates are two times slower now
   87.57 + - LFO amplitude (tremolo) and phase modulation (vibrato)
   87.58 + - rhythm sounds phase generation
   87.59 + - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)
   87.60 + - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)
   87.61 + - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)
   87.62 +
   87.63 +12-28-2001 Acho A. Tang
   87.64 + - reflected Delta-T EOS status on Y8950 status port.
   87.65 + - fixed subscription range of attack/decay tables
   87.66 +
   87.67 +
   87.68 +    To do:
   87.69 +        add delay before key off in CSM mode (see CSMKeyControll)
   87.70 +        verify volume of the FM part on the Y8950
   87.71 +*/
   87.72 +
   87.73 +#include <stdio.h>
   87.74 +#include <stdint.h>
   87.75 +#include <math.h>
   87.76 +#include <string.h>
   87.77 +#include <stdlib.h>
   87.78 +//#include "emu.h"
   87.79 +//#include "ymdeltat.h"
   87.80 +#include "fmopl.h"
   87.81 +
   87.82 +
   87.83 +
   87.84 +/* output final shift */
   87.85 +#if (OPL_SAMPLE_BITS==16)
   87.86 +	#define FINAL_SH	(0)
   87.87 +	#define MAXOUT		(+32767)
   87.88 +	#define MINOUT		(-32768)
   87.89 +#else
   87.90 +	#define FINAL_SH	(8)
   87.91 +	#define MAXOUT		(+127)
   87.92 +	#define MINOUT		(-128)
   87.93 +#endif
   87.94 +
   87.95 +
   87.96 +#define FREQ_SH			16  /* 16.16 fixed point (frequency calculations) */
   87.97 +#define EG_SH			16  /* 16.16 fixed point (EG timing)              */
   87.98 +#define LFO_SH			24  /*  8.24 fixed point (LFO calculations)       */
   87.99 +#define TIMER_SH		16  /* 16.16 fixed point (timers calculations)    */
  87.100 +
  87.101 +#define FREQ_MASK		((1<<FREQ_SH)-1)
  87.102 +
  87.103 +/* envelope output entries */
  87.104 +#define ENV_BITS		10
  87.105 +#define ENV_LEN			(1<<ENV_BITS)
  87.106 +#define ENV_STEP		(128.0/ENV_LEN)
  87.107 +
  87.108 +#define MAX_ATT_INDEX	((1<<(ENV_BITS-1))-1) /*511*/
  87.109 +#define MIN_ATT_INDEX	(0)
  87.110 +
  87.111 +/* sinwave entries */
  87.112 +#define SIN_BITS		10
  87.113 +#define SIN_LEN			(1<<SIN_BITS)
  87.114 +#define SIN_MASK		(SIN_LEN-1)
  87.115 +
  87.116 +#define TL_RES_LEN		(256)	/* 8 bits addressing (real chip) */
  87.117 +
  87.118 +
  87.119 +
  87.120 +/* register number to channel number , slot offset */
  87.121 +#define SLOT1 0
  87.122 +#define SLOT2 1
  87.123 +
  87.124 +/* Envelope Generator phases */
  87.125 +
  87.126 +#define EG_ATT			4
  87.127 +#define EG_DEC			3
  87.128 +#define EG_SUS			2
  87.129 +#define EG_REL			1
  87.130 +#define EG_OFF			0
  87.131 +
  87.132 +
  87.133 +/* save output as raw 16-bit sample */
  87.134 +
  87.135 +/*#define SAVE_SAMPLE*/
  87.136 +
  87.137 +#ifdef SAVE_SAMPLE
  87.138 +INLINE signed int acc_calc(signed int value)
  87.139 +{
  87.140 +	if (value>=0)
  87.141 +	{
  87.142 +		if (value < 0x0200)
  87.143 +			return (value & ~0);
  87.144 +		if (value < 0x0400)
  87.145 +			return (value & ~1);
  87.146 +		if (value < 0x0800)
  87.147 +			return (value & ~3);
  87.148 +		if (value < 0x1000)
  87.149 +			return (value & ~7);
  87.150 +		if (value < 0x2000)
  87.151 +			return (value & ~15);
  87.152 +		if (value < 0x4000)
  87.153 +			return (value & ~31);
  87.154 +		return (value & ~63);
  87.155 +	}
  87.156 +	/*else value < 0*/
  87.157 +	if (value > -0x0200)
  87.158 +		return (~abs(value) & ~0);
  87.159 +	if (value > -0x0400)
  87.160 +		return (~abs(value) & ~1);
  87.161 +	if (value > -0x0800)
  87.162 +		return (~abs(value) & ~3);
  87.163 +	if (value > -0x1000)
  87.164 +		return (~abs(value) & ~7);
  87.165 +	if (value > -0x2000)
  87.166 +		return (~abs(value) & ~15);
  87.167 +	if (value > -0x4000)
  87.168 +		return (~abs(value) & ~31);
  87.169 +	return (~abs(value) & ~63);
  87.170 +}
  87.171 +
  87.172 +
  87.173 +static FILE *sample[1];
  87.174 +	#if 1	/*save to MONO file */
  87.175 +		#define SAVE_ALL_CHANNELS \
  87.176 +		{	signed int pom = acc_calc(lt); \
  87.177 +			fputc((unsigned short)pom&0xff,sample[0]); \
  87.178 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  87.179 +		}
  87.180 +	#else	/*save to STEREO file */
  87.181 +		#define SAVE_ALL_CHANNELS \
  87.182 +		{	signed int pom = lt; \
  87.183 +			fputc((unsigned short)pom&0xff,sample[0]); \
  87.184 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  87.185 +			pom = rt; \
  87.186 +			fputc((unsigned short)pom&0xff,sample[0]); \
  87.187 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  87.188 +		}
  87.189 +	#endif
  87.190 +#endif
  87.191 +
  87.192 +#define LOG_CYM_FILE 0
  87.193 +static FILE * cymfile = NULL;
  87.194 +
  87.195 +
  87.196 +
  87.197 +#define OPL_TYPE_WAVESEL   0x01  /* waveform select     */
  87.198 +#define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit  */
  87.199 +#define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface  */
  87.200 +#define OPL_TYPE_IO        0x08  /* I/O port            */
  87.201 +
  87.202 +/* ---------- Generic interface section ---------- */
  87.203 +#define OPL_TYPE_YM3526 (0)
  87.204 +#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
  87.205 +#define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
  87.206 +
  87.207 +
  87.208 +
  87.209 +typedef struct{
  87.210 +	UINT32	ar;			/* attack rate: AR<<2           */
  87.211 +	UINT32	dr;			/* decay rate:  DR<<2           */
  87.212 +	UINT32	rr;			/* release rate:RR<<2           */
  87.213 +	UINT8	KSR;		/* key scale rate               */
  87.214 +	UINT8	ksl;		/* keyscale level               */
  87.215 +	UINT8	ksr;		/* key scale rate: kcode>>KSR   */
  87.216 +	UINT8	mul;		/* multiple: mul_tab[ML]        */
  87.217 +
  87.218 +	/* Phase Generator */
  87.219 +	UINT32	Cnt;		/* frequency counter            */
  87.220 +	UINT32	Incr;		/* frequency counter step       */
  87.221 +	UINT8   FB;			/* feedback shift value         */
  87.222 +	INT32   *connect1;	/* slot1 output pointer         */
  87.223 +	INT32   op1_out[2];	/* slot1 output for feedback    */
  87.224 +	UINT8   CON;		/* connection (algorithm) type  */
  87.225 +
  87.226 +	/* Envelope Generator */
  87.227 +	UINT8	eg_type;	/* percussive/non-percussive mode */
  87.228 +	UINT8	state;		/* phase type                   */
  87.229 +	UINT32	TL;			/* total level: TL << 2         */
  87.230 +	INT32	TLL;		/* adjusted now TL              */
  87.231 +	INT32	volume;		/* envelope counter             */
  87.232 +	UINT32	sl;			/* sustain level: sl_tab[SL]    */
  87.233 +	UINT8	eg_sh_ar;	/* (attack state)               */
  87.234 +	UINT8	eg_sel_ar;	/* (attack state)               */
  87.235 +	UINT8	eg_sh_dr;	/* (decay state)                */
  87.236 +	UINT8	eg_sel_dr;	/* (decay state)                */
  87.237 +	UINT8	eg_sh_rr;	/* (release state)              */
  87.238 +	UINT8	eg_sel_rr;	/* (release state)              */
  87.239 +	UINT32	key;		/* 0 = KEY OFF, >0 = KEY ON     */
  87.240 +
  87.241 +	/* LFO */
  87.242 +	UINT32	AMmask;		/* LFO Amplitude Modulation enable mask */
  87.243 +	UINT8	vib;		/* LFO Phase Modulation enable flag (active high)*/
  87.244 +
  87.245 +	/* waveform select */
  87.246 +	UINT16	wavetable;
  87.247 +} OPL_SLOT;
  87.248 +
  87.249 +typedef struct{
  87.250 +	OPL_SLOT SLOT[2];
  87.251 +	/* phase generator state */
  87.252 +	UINT32  block_fnum;	/* block+fnum                   */
  87.253 +	UINT32  fc;			/* Freq. Increment base         */
  87.254 +	UINT32  ksl_base;	/* KeyScaleLevel Base step      */
  87.255 +	UINT8   kcode;		/* key code (for key scaling)   */
  87.256 +} OPL_CH;
  87.257 +
  87.258 +/* OPL state */
  87.259 +typedef struct fm_opl_f {
  87.260 +	/* FM channel slots */
  87.261 +	OPL_CH	P_CH[9];				/* OPL/OPL2 chips have 9 channels*/
  87.262 +
  87.263 +	UINT32	eg_cnt;					/* global envelope generator counter    */
  87.264 +	UINT32	eg_timer;				/* global envelope generator counter works at frequency = chipclock/72 */
  87.265 +	UINT32	eg_timer_add;			/* step of eg_timer                     */
  87.266 +	UINT32	eg_timer_overflow;		/* envelope generator timer overlfows every 1 sample (on real chip) */
  87.267 +
  87.268 +	UINT8	rhythm;					/* Rhythm mode                  */
  87.269 +
  87.270 +	UINT32	fn_tab[1024];			/* fnumber->increment counter   */
  87.271 +
  87.272 +	/* LFO */
  87.273 +	UINT8	lfo_am_depth;
  87.274 +	UINT8	lfo_pm_depth_range;
  87.275 +	UINT32	lfo_am_cnt;
  87.276 +	UINT32	lfo_am_inc;
  87.277 +	UINT32	lfo_pm_cnt;
  87.278 +	UINT32	lfo_pm_inc;
  87.279 +
  87.280 +	UINT32	noise_rng;				/* 23 bit noise shift register  */
  87.281 +	UINT32	noise_p;				/* current noise 'phase'        */
  87.282 +	UINT32	noise_f;				/* current noise period         */
  87.283 +
  87.284 +	UINT8	wavesel;				/* waveform select enable flag  */
  87.285 +
  87.286 +	UINT32	T[2];					/* timer counters               */
  87.287 +	UINT8	st[2];					/* timer enable                 */
  87.288 +
  87.289 +#if BUILD_Y8950
  87.290 +	/* Delta-T ADPCM unit (Y8950) */
  87.291 +
  87.292 +	YM_DELTAT *deltat;
  87.293 +
  87.294 +	/* Keyboard and I/O ports interface */
  87.295 +	UINT8	portDirection;
  87.296 +	UINT8	portLatch;
  87.297 +	OPL_PORTHANDLER_R porthandler_r;
  87.298 +	OPL_PORTHANDLER_W porthandler_w;
  87.299 +	void *	port_param;
  87.300 +	OPL_PORTHANDLER_R keyboardhandler_r;
  87.301 +	OPL_PORTHANDLER_W keyboardhandler_w;
  87.302 +	void *	keyboard_param;
  87.303 +#endif
  87.304 +
  87.305 +	/* external event callback handlers */
  87.306 +	OPL_TIMERHANDLER  timer_handler;	/* TIMER handler                */
  87.307 +	void *TimerParam;					/* TIMER parameter              */
  87.308 +	OPL_IRQHANDLER    IRQHandler;	/* IRQ handler                  */
  87.309 +	void *IRQParam;					/* IRQ parameter                */
  87.310 +	OPL_UPDATEHANDLER UpdateHandler;/* stream update handler        */
  87.311 +	void *UpdateParam;				/* stream update parameter      */
  87.312 +
  87.313 +	UINT8 type;						/* chip type                    */
  87.314 +	UINT8 address;					/* address register             */
  87.315 +	UINT8 status;					/* status flag                  */
  87.316 +	UINT8 statusmask;				/* status mask                  */
  87.317 +	UINT8 mode;						/* Reg.08 : CSM,notesel,etc.    */
  87.318 +
  87.319 +	UINT32 clock;					/* master clock  (Hz)           */
  87.320 +	UINT32 rate;					/* sampling rate (Hz)           */
  87.321 +	double freqbase;				/* frequency base               */
  87.322 +	attotime TimerBase;			/* Timer base time (==sampling time)*/
  87.323 +	running_device *device;
  87.324 +} FM_OPL;
  87.325 +
  87.326 +
  87.327 +
  87.328 +/* mapping of register number (offset) to slot number used by the emulator */
  87.329 +static const int slot_array[32]=
  87.330 +{
  87.331 +	 0, 2, 4, 1, 3, 5,-1,-1,
  87.332 +	 6, 8,10, 7, 9,11,-1,-1,
  87.333 +	12,14,16,13,15,17,-1,-1,
  87.334 +	-1,-1,-1,-1,-1,-1,-1,-1
  87.335 +};
  87.336 +
  87.337 +/* key scale level */
  87.338 +/* table is 3dB/octave , DV converts this into 6dB/octave */
  87.339 +/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
  87.340 +#define DV (0.1875/2.0)
  87.341 +static const UINT32 ksl_tab[8*16]=
  87.342 +{
  87.343 +	/* OCT 0 */
  87.344 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.345 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.346 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.347 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.348 +	/* OCT 1 */
  87.349 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.350 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.351 +	 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
  87.352 +	 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
  87.353 +	/* OCT 2 */
  87.354 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  87.355 +	 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
  87.356 +	 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
  87.357 +	 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
  87.358 +	/* OCT 3 */
  87.359 +	 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
  87.360 +	 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
  87.361 +	 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
  87.362 +	 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
  87.363 +	/* OCT 4 */
  87.364 +	 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
  87.365 +	 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
  87.366 +	 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
  87.367 +	10.875/DV,11.250/DV,11.625/DV,12.000/DV,
  87.368 +	/* OCT 5 */
  87.369 +	 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
  87.370 +	 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
  87.371 +	12.000/DV,12.750/DV,13.125/DV,13.500/DV,
  87.372 +	13.875/DV,14.250/DV,14.625/DV,15.000/DV,
  87.373 +	/* OCT 6 */
  87.374 +	 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
  87.375 +	12.000/DV,13.125/DV,13.875/DV,14.625/DV,
  87.376 +	15.000/DV,15.750/DV,16.125/DV,16.500/DV,
  87.377 +	16.875/DV,17.250/DV,17.625/DV,18.000/DV,
  87.378 +	/* OCT 7 */
  87.379 +	 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
  87.380 +	15.000/DV,16.125/DV,16.875/DV,17.625/DV,
  87.381 +	18.000/DV,18.750/DV,19.125/DV,19.500/DV,
  87.382 +	19.875/DV,20.250/DV,20.625/DV,21.000/DV
  87.383 +};
  87.384 +#undef DV
  87.385 +
  87.386 +/* sustain level table (3dB per step) */
  87.387 +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
  87.388 +#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
  87.389 +static const UINT32 sl_tab[16]={
  87.390 + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
  87.391 + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
  87.392 +};
  87.393 +#undef SC
  87.394 +
  87.395 +
  87.396 +#define RATE_STEPS (8)
  87.397 +static const unsigned char eg_inc[15*RATE_STEPS]={
  87.398 +
  87.399 +/*cycle:0 1  2 3  4 5  6 7*/
  87.400 +
  87.401 +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
  87.402 +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
  87.403 +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
  87.404 +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
  87.405 +
  87.406 +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
  87.407 +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
  87.408 +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
  87.409 +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
  87.410 +
  87.411 +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
  87.412 +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
  87.413 +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
  87.414 +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
  87.415 +
  87.416 +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
  87.417 +/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
  87.418 +/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
  87.419 +};
  87.420 +
  87.421 +
  87.422 +#define O(a) (a*RATE_STEPS)
  87.423 +
  87.424 +/*note that there is no O(13) in this table - it's directly in the code */
  87.425 +static const unsigned char eg_rate_select[16+64+16]={	/* Envelope Generator rates (16 + 64 rates + 16 RKS) */
  87.426 +/* 16 infinite time rates */
  87.427 +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
  87.428 +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
  87.429 +
  87.430 +/* rates 00-12 */
  87.431 +O( 0),O( 1),O( 2),O( 3),
  87.432 +O( 0),O( 1),O( 2),O( 3),
  87.433 +O( 0),O( 1),O( 2),O( 3),
  87.434 +O( 0),O( 1),O( 2),O( 3),
  87.435 +O( 0),O( 1),O( 2),O( 3),
  87.436 +O( 0),O( 1),O( 2),O( 3),
  87.437 +O( 0),O( 1),O( 2),O( 3),
  87.438 +O( 0),O( 1),O( 2),O( 3),
  87.439 +O( 0),O( 1),O( 2),O( 3),
  87.440 +O( 0),O( 1),O( 2),O( 3),
  87.441 +O( 0),O( 1),O( 2),O( 3),
  87.442 +O( 0),O( 1),O( 2),O( 3),
  87.443 +O( 0),O( 1),O( 2),O( 3),
  87.444 +
  87.445 +/* rate 13 */
  87.446 +O( 4),O( 5),O( 6),O( 7),
  87.447 +
  87.448 +/* rate 14 */
  87.449 +O( 8),O( 9),O(10),O(11),
  87.450 +
  87.451 +/* rate 15 */
  87.452 +O(12),O(12),O(12),O(12),
  87.453 +
  87.454 +/* 16 dummy rates (same as 15 3) */
  87.455 +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
  87.456 +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
  87.457 +
  87.458 +};
  87.459 +#undef O
  87.460 +
  87.461 +/*rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15 */
  87.462 +/*shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0  */
  87.463 +/*mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0  */
  87.464 +
  87.465 +#define O(a) (a*1)
  87.466 +static const unsigned char eg_rate_shift[16+64+16]={	/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
  87.467 +/* 16 infinite time rates */
  87.468 +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
  87.469 +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
  87.470 +
  87.471 +/* rates 00-12 */
  87.472 +O(12),O(12),O(12),O(12),
  87.473 +O(11),O(11),O(11),O(11),
  87.474 +O(10),O(10),O(10),O(10),
  87.475 +O( 9),O( 9),O( 9),O( 9),
  87.476 +O( 8),O( 8),O( 8),O( 8),
  87.477 +O( 7),O( 7),O( 7),O( 7),
  87.478 +O( 6),O( 6),O( 6),O( 6),
  87.479 +O( 5),O( 5),O( 5),O( 5),
  87.480 +O( 4),O( 4),O( 4),O( 4),
  87.481 +O( 3),O( 3),O( 3),O( 3),
  87.482 +O( 2),O( 2),O( 2),O( 2),
  87.483 +O( 1),O( 1),O( 1),O( 1),
  87.484 +O( 0),O( 0),O( 0),O( 0),
  87.485 +
  87.486 +/* rate 13 */
  87.487 +O( 0),O( 0),O( 0),O( 0),
  87.488 +
  87.489 +/* rate 14 */
  87.490 +O( 0),O( 0),O( 0),O( 0),
  87.491 +
  87.492 +/* rate 15 */
  87.493 +O( 0),O( 0),O( 0),O( 0),
  87.494 +
  87.495 +/* 16 dummy rates (same as 15 3) */
  87.496 +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
  87.497 +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
  87.498 +
  87.499 +};
  87.500 +#undef O
  87.501 +
  87.502 +
  87.503 +/* multiple table */
  87.504 +#define ML 2
  87.505 +static const UINT8 mul_tab[16]= {
  87.506 +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
  87.507 +   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
  87.508 +   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
  87.509 +};
  87.510 +#undef ML
  87.511 +
  87.512 +/*  TL_TAB_LEN is calculated as:
  87.513 +*   12 - sinus amplitude bits     (Y axis)
  87.514 +*   2  - sinus sign bit           (Y axis)
  87.515 +*   TL_RES_LEN - sinus resolution (X axis)
  87.516 +*/
  87.517 +#define TL_TAB_LEN (12*2*TL_RES_LEN)
  87.518 +static signed int tl_tab[TL_TAB_LEN];
  87.519 +
  87.520 +#define ENV_QUIET		(TL_TAB_LEN>>4)
  87.521 +
  87.522 +/* sin waveform table in 'decibel' scale */
  87.523 +/* four waveforms on OPL2 type chips */
  87.524 +static unsigned int sin_tab[SIN_LEN * 4];
  87.525 +
  87.526 +
  87.527 +/* LFO Amplitude Modulation table (verified on real YM3812)
  87.528 +   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
  87.529 +
  87.530 +   Length: 210 elements.
  87.531 +
  87.532 +    Each of the elements has to be repeated
  87.533 +    exactly 64 times (on 64 consecutive samples).
  87.534 +    The whole table takes: 64 * 210 = 13440 samples.
  87.535 +
  87.536 +    When AM = 1 data is used directly
  87.537 +    When AM = 0 data is divided by 4 before being used (loosing precision is important)
  87.538 +*/
  87.539 +
  87.540 +#define LFO_AM_TAB_ELEMENTS 210
  87.541 +
  87.542 +static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
  87.543 +0,0,0,0,0,0,0,
  87.544 +1,1,1,1,
  87.545 +2,2,2,2,
  87.546 +3,3,3,3,
  87.547 +4,4,4,4,
  87.548 +5,5,5,5,
  87.549 +6,6,6,6,
  87.550 +7,7,7,7,
  87.551 +8,8,8,8,
  87.552 +9,9,9,9,
  87.553 +10,10,10,10,
  87.554 +11,11,11,11,
  87.555 +12,12,12,12,
  87.556 +13,13,13,13,
  87.557 +14,14,14,14,
  87.558 +15,15,15,15,
  87.559 +16,16,16,16,
  87.560 +17,17,17,17,
  87.561 +18,18,18,18,
  87.562 +19,19,19,19,
  87.563 +20,20,20,20,
  87.564 +21,21,21,21,
  87.565 +22,22,22,22,
  87.566 +23,23,23,23,
  87.567 +24,24,24,24,
  87.568 +25,25,25,25,
  87.569 +26,26,26,
  87.570 +25,25,25,25,
  87.571 +24,24,24,24,
  87.572 +23,23,23,23,
  87.573 +22,22,22,22,
  87.574 +21,21,21,21,
  87.575 +20,20,20,20,
  87.576 +19,19,19,19,
  87.577 +18,18,18,18,
  87.578 +17,17,17,17,
  87.579 +16,16,16,16,
  87.580 +15,15,15,15,
  87.581 +14,14,14,14,
  87.582 +13,13,13,13,
  87.583 +12,12,12,12,
  87.584 +11,11,11,11,
  87.585 +10,10,10,10,
  87.586 +9,9,9,9,
  87.587 +8,8,8,8,
  87.588 +7,7,7,7,
  87.589 +6,6,6,6,
  87.590 +5,5,5,5,
  87.591 +4,4,4,4,
  87.592 +3,3,3,3,
  87.593 +2,2,2,2,
  87.594 +1,1,1,1
  87.595 +};
  87.596 +
  87.597 +/* LFO Phase Modulation table (verified on real YM3812) */
  87.598 +static const INT8 lfo_pm_table[8*8*2] = {
  87.599 +
  87.600 +/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
  87.601 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
  87.602 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 1*/
  87.603 +
  87.604 +/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */
  87.605 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
  87.606 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 1*/
  87.607 +
  87.608 +/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */
  87.609 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
  87.610 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 1*/
  87.611 +
  87.612 +/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */
  87.613 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
  87.614 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 1*/
  87.615 +
  87.616 +/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */
  87.617 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
  87.618 +4, 2, 0,-2,-4,-2, 0, 2,	/*LFO PM depth = 1*/
  87.619 +
  87.620 +/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */
  87.621 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
  87.622 +5, 2, 0,-2,-5,-2, 0, 2,	/*LFO PM depth = 1*/
  87.623 +
  87.624 +/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */
  87.625 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
  87.626 +6, 3, 0,-3,-6,-3, 0, 3,	/*LFO PM depth = 1*/
  87.627 +
  87.628 +/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */
  87.629 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
  87.630 +7, 3, 0,-3,-7,-3, 0, 3	/*LFO PM depth = 1*/
  87.631 +};
  87.632 +
  87.633 +
  87.634 +/* lock level of common table */
  87.635 +static int num_lock = 0;
  87.636 +
  87.637 +
  87.638 +static void *cur_chip = NULL;	/* current chip pointer */
  87.639 +static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
  87.640 +
  87.641 +static signed int phase_modulation;	/* phase modulation input (SLOT 2) */
  87.642 +static signed int output[1];
  87.643 +
  87.644 +#if BUILD_Y8950
  87.645 +static INT32 output_deltat[4];		/* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
  87.646 +#endif
  87.647 +
  87.648 +static UINT32	LFO_AM;
  87.649 +static INT32	LFO_PM;
  87.650 +
  87.651 +
  87.652 +
  87.653 +INLINE int limit( int val, int max, int min ) {
  87.654 +	if ( val > max )
  87.655 +		val = max;
  87.656 +	else if ( val < min )
  87.657 +		val = min;
  87.658 +
  87.659 +	return val;
  87.660 +}
  87.661 +
  87.662 +
  87.663 +/* status set and IRQ handling */
  87.664 +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
  87.665 +{
  87.666 +	/* set status flag */
  87.667 +	OPL->status |= flag;
  87.668 +	if(!(OPL->status & 0x80))
  87.669 +	{
  87.670 +		if(OPL->status & OPL->statusmask)
  87.671 +		{	/* IRQ on */
  87.672 +			OPL->status |= 0x80;
  87.673 +			/* callback user interrupt handler (IRQ is OFF to ON) */
  87.674 +			if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
  87.675 +		}
  87.676 +	}
  87.677 +}
  87.678 +
  87.679 +/* status reset and IRQ handling */
  87.680 +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
  87.681 +{
  87.682 +	/* reset status flag */
  87.683 +	OPL->status &=~flag;
  87.684 +	if((OPL->status & 0x80))
  87.685 +	{
  87.686 +		if (!(OPL->status & OPL->statusmask) )
  87.687 +		{
  87.688 +			OPL->status &= 0x7f;
  87.689 +			/* callback user interrupt handler (IRQ is ON to OFF) */
  87.690 +			if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
  87.691 +		}
  87.692 +	}
  87.693 +}
  87.694 +
  87.695 +/* IRQ mask set */
  87.696 +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
  87.697 +{
  87.698 +	OPL->statusmask = flag;
  87.699 +	/* IRQ handling check */
  87.700 +	OPL_STATUS_SET(OPL,0);
  87.701 +	OPL_STATUS_RESET(OPL,0);
  87.702 +}
  87.703 +
  87.704 +
  87.705 +/* advance LFO to next sample */
  87.706 +INLINE void advance_lfo(FM_OPL *OPL)
  87.707 +{
  87.708 +	UINT8 tmp;
  87.709 +
  87.710 +	/* LFO */
  87.711 +	OPL->lfo_am_cnt += OPL->lfo_am_inc;
  87.712 +	if (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )	/* lfo_am_table is 210 elements long */
  87.713 +		OPL->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);
  87.714 +
  87.715 +	tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];
  87.716 +
  87.717 +	if (OPL->lfo_am_depth)
  87.718 +		LFO_AM = tmp;
  87.719 +	else
  87.720 +		LFO_AM = tmp>>2;
  87.721 +
  87.722 +	OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
  87.723 +	LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
  87.724 +}
  87.725 +
  87.726 +/* advance to next sample */
  87.727 +INLINE void advance(FM_OPL *OPL)
  87.728 +{
  87.729 +	OPL_CH *CH;
  87.730 +	OPL_SLOT *op;
  87.731 +	int i;
  87.732 +
  87.733 +	OPL->eg_timer += OPL->eg_timer_add;
  87.734 +
  87.735 +	while (OPL->eg_timer >= OPL->eg_timer_overflow)
  87.736 +	{
  87.737 +		OPL->eg_timer -= OPL->eg_timer_overflow;
  87.738 +
  87.739 +		OPL->eg_cnt++;
  87.740 +
  87.741 +		for (i=0; i<9*2; i++)
  87.742 +		{
  87.743 +			CH  = &OPL->P_CH[i/2];
  87.744 +			op  = &CH->SLOT[i&1];
  87.745 +
  87.746 +			/* Envelope Generator */
  87.747 +			switch(op->state)
  87.748 +			{
  87.749 +			case EG_ATT:		/* attack phase */
  87.750 +				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
  87.751 +				{
  87.752 +					op->volume += (~op->volume *
  87.753 +	                        		           (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])
  87.754 +        			                          ) >>3;
  87.755 +
  87.756 +					if (op->volume <= MIN_ATT_INDEX)
  87.757 +					{
  87.758 +						op->volume = MIN_ATT_INDEX;
  87.759 +						op->state = EG_DEC;
  87.760 +					}
  87.761 +
  87.762 +				}
  87.763 +			break;
  87.764 +
  87.765 +			case EG_DEC:	/* decay phase */
  87.766 +				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
  87.767 +				{
  87.768 +					op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
  87.769 +
  87.770 +					if ( op->volume >= op->sl )
  87.771 +						op->state = EG_SUS;
  87.772 +
  87.773 +				}
  87.774 +			break;
  87.775 +
  87.776 +			case EG_SUS:	/* sustain phase */
  87.777 +
  87.778 +				/* this is important behaviour:
  87.779 +                one can change percusive/non-percussive modes on the fly and
  87.780 +                the chip will remain in sustain phase - verified on real YM3812 */
  87.781 +
  87.782 +				if(op->eg_type)		/* non-percussive mode */
  87.783 +				{
  87.784 +									/* do nothing */
  87.785 +				}
  87.786 +				else				/* percussive mode */
  87.787 +				{
  87.788 +					/* during sustain phase chip adds Release Rate (in percussive mode) */
  87.789 +					if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
  87.790 +					{
  87.791 +						op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
  87.792 +
  87.793 +						if ( op->volume >= MAX_ATT_INDEX )
  87.794 +							op->volume = MAX_ATT_INDEX;
  87.795 +					}
  87.796 +					/* else do nothing in sustain phase */
  87.797 +				}
  87.798 +			break;
  87.799 +
  87.800 +			case EG_REL:	/* release phase */
  87.801 +				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
  87.802 +				{
  87.803 +					op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
  87.804 +
  87.805 +					if ( op->volume >= MAX_ATT_INDEX )
  87.806 +					{
  87.807 +						op->volume = MAX_ATT_INDEX;
  87.808 +						op->state = EG_OFF;
  87.809 +					}
  87.810 +
  87.811 +				}
  87.812 +			break;
  87.813 +
  87.814 +			default:
  87.815 +			break;
  87.816 +			}
  87.817 +		}
  87.818 +	}
  87.819 +
  87.820 +	for (i=0; i<9*2; i++)
  87.821 +	{
  87.822 +		CH  = &OPL->P_CH[i/2];
  87.823 +		op  = &CH->SLOT[i&1];
  87.824 +
  87.825 +		/* Phase Generator */
  87.826 +		if(op->vib)
  87.827 +		{
  87.828 +			UINT8 block;
  87.829 +			unsigned int block_fnum = CH->block_fnum;
  87.830 +
  87.831 +			unsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;
  87.832 +
  87.833 +			signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
  87.834 +
  87.835 +			if (lfo_fn_table_index_offset)	/* LFO phase modulation active */
  87.836 +			{
  87.837 +				block_fnum += lfo_fn_table_index_offset;
  87.838 +				block = (block_fnum&0x1c00) >> 10;
  87.839 +				op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
  87.840 +			}
  87.841 +			else	/* LFO phase modulation  = zero */
  87.842 +			{
  87.843 +				op->Cnt += op->Incr;
  87.844 +			}
  87.845 +		}
  87.846 +		else	/* LFO phase modulation disabled for this operator */
  87.847 +		{
  87.848 +			op->Cnt += op->Incr;
  87.849 +		}
  87.850 +	}
  87.851 +
  87.852 +	/*  The Noise Generator of the YM3812 is 23-bit shift register.
  87.853 +    *   Period is equal to 2^23-2 samples.
  87.854 +    *   Register works at sampling frequency of the chip, so output
  87.855 +    *   can change on every sample.
  87.856 +    *
  87.857 +    *   Output of the register and input to the bit 22 is:
  87.858 +    *   bit0 XOR bit14 XOR bit15 XOR bit22
  87.859 +    *
  87.860 +    *   Simply use bit 22 as the noise output.
  87.861 +    */
  87.862 +
  87.863 +	OPL->noise_p += OPL->noise_f;
  87.864 +	i = OPL->noise_p >> FREQ_SH;		/* number of events (shifts of the shift register) */
  87.865 +	OPL->noise_p &= FREQ_MASK;
  87.866 +	while (i)
  87.867 +	{
  87.868 +		/*
  87.869 +        UINT32 j;
  87.870 +        j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
  87.871 +        OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
  87.872 +        */
  87.873 +
  87.874 +		/*
  87.875 +            Instead of doing all the logic operations above, we
  87.876 +            use a trick here (and use bit 0 as the noise output).
  87.877 +            The difference is only that the noise bit changes one
  87.878 +            step ahead. This doesn't matter since we don't know
  87.879 +            what is real state of the noise_rng after the reset.
  87.880 +        */
  87.881 +
  87.882 +		if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;
  87.883 +		OPL->noise_rng >>= 1;
  87.884 +
  87.885 +		i--;
  87.886 +	}
  87.887 +}
  87.888 +
  87.889 +
  87.890 +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
  87.891 +{
  87.892 +	UINT32 p;
  87.893 +
  87.894 +	p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
  87.895 +
  87.896 +	if (p >= TL_TAB_LEN)
  87.897 +		return 0;
  87.898 +	return tl_tab[p];
  87.899 +}
  87.900 +
  87.901 +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
  87.902 +{
  87.903 +	UINT32 p;
  87.904 +
  87.905 +	p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm      )) >> FREQ_SH ) & SIN_MASK) ];
  87.906 +
  87.907 +	if (p >= TL_TAB_LEN)
  87.908 +		return 0;
  87.909 +	return tl_tab[p];
  87.910 +}
  87.911 +
  87.912 +
  87.913 +#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
  87.914 +
  87.915 +/* calculate output */
  87.916 +INLINE void OPL_CALC_CH( OPL_CH *CH )
  87.917 +{
  87.918 +	OPL_SLOT *SLOT;
  87.919 +	unsigned int env;
  87.920 +	signed int out;
  87.921 +
  87.922 +	phase_modulation = 0;
  87.923 +
  87.924 +	/* SLOT 1 */
  87.925 +	SLOT = &CH->SLOT[SLOT1];
  87.926 +	env  = volume_calc(SLOT);
  87.927 +	out  = SLOT->op1_out[0] + SLOT->op1_out[1];
  87.928 +	SLOT->op1_out[0] = SLOT->op1_out[1];
  87.929 +	*SLOT->connect1 += SLOT->op1_out[0];
  87.930 +	SLOT->op1_out[1] = 0;
  87.931 +	if( env < ENV_QUIET )
  87.932 +	{
  87.933 +		if (!SLOT->FB)
  87.934 +			out = 0;
  87.935 +		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
  87.936 +	}
  87.937 +
  87.938 +	/* SLOT 2 */
  87.939 +	SLOT++;
  87.940 +	env = volume_calc(SLOT);
  87.941 +	if( env < ENV_QUIET )
  87.942 +		output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
  87.943 +}
  87.944 +
  87.945 +/*
  87.946 +    operators used in the rhythm sounds generation process:
  87.947 +
  87.948 +    Envelope Generator:
  87.949 +
  87.950 +channel  operator  register number   Bass  High  Snare Tom  Top
  87.951 +/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal
  87.952 + 6 / 0   12        50  70   90   f0  +
  87.953 + 6 / 1   15        53  73   93   f3  +
  87.954 + 7 / 0   13        51  71   91   f1        +
  87.955 + 7 / 1   16        54  74   94   f4              +
  87.956 + 8 / 0   14        52  72   92   f2                    +
  87.957 + 8 / 1   17        55  75   95   f5                          +
  87.958 +
  87.959 +    Phase Generator:
  87.960 +
  87.961 +channel  operator  register number   Bass  High  Snare Tom  Top
  87.962 +/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal
  87.963 + 6 / 0   12        30                +
  87.964 + 6 / 1   15        33                +
  87.965 + 7 / 0   13        31                      +     +           +
  87.966 + 7 / 1   16        34                -----  n o t  u s e d -----
  87.967 + 8 / 0   14        32                                  +
  87.968 + 8 / 1   17        35                      +                 +
  87.969 +
  87.970 +channel  operator  register number   Bass  High  Snare Tom  Top
  87.971 +number   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal
  87.972 +   6     12,15     B6        A6      +
  87.973 +
  87.974 +   7     13,16     B7        A7            +     +           +
  87.975 +
  87.976 +   8     14,17     B8        A8            +           +     +
  87.977 +
  87.978 +*/
  87.979 +
  87.980 +/* calculate rhythm */
  87.981 +
  87.982 +INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
  87.983 +{
  87.984 +	OPL_SLOT *SLOT;
  87.985 +	signed int out;
  87.986 +	unsigned int env;
  87.987 +
  87.988 +
  87.989 +	/* Bass Drum (verified on real YM3812):
  87.990 +      - depends on the channel 6 'connect' register:
  87.991 +          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
  87.992 +          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
  87.993 +      - output sample always is multiplied by 2
  87.994 +    */
  87.995 +
  87.996 +	phase_modulation = 0;
  87.997 +	/* SLOT 1 */
  87.998 +	SLOT = &CH[6].SLOT[SLOT1];
  87.999 +	env = volume_calc(SLOT);
 87.1000 +
 87.1001 +	out = SLOT->op1_out[0] + SLOT->op1_out[1];
 87.1002 +	SLOT->op1_out[0] = SLOT->op1_out[1];
 87.1003 +
 87.1004 +	if (!SLOT->CON)
 87.1005 +		phase_modulation = SLOT->op1_out[0];
 87.1006 +	/* else ignore output of operator 1 */
 87.1007 +
 87.1008 +	SLOT->op1_out[1] = 0;
 87.1009 +	if( env < ENV_QUIET )
 87.1010 +	{
 87.1011 +		if (!SLOT->FB)
 87.1012 +			out = 0;
 87.1013 +		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
 87.1014 +	}
 87.1015 +
 87.1016 +	/* SLOT 2 */
 87.1017 +	SLOT++;
 87.1018 +	env = volume_calc(SLOT);
 87.1019 +	if( env < ENV_QUIET )
 87.1020 +		output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
 87.1021 +
 87.1022 +
 87.1023 +	/* Phase generation is based on: */
 87.1024 +	/* HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
 87.1025 +	/* SD  (16) channel 7->slot 1 */
 87.1026 +	/* TOM (14) channel 8->slot 1 */
 87.1027 +	/* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
 87.1028 +
 87.1029 +	/* Envelope generation based on: */
 87.1030 +	/* HH  channel 7->slot1 */
 87.1031 +	/* SD  channel 7->slot2 */
 87.1032 +	/* TOM channel 8->slot1 */
 87.1033 +	/* TOP channel 8->slot2 */
 87.1034 +
 87.1035 +
 87.1036 +	/* The following formulas can be well optimized.
 87.1037 +       I leave them in direct form for now (in case I've missed something).
 87.1038 +    */
 87.1039 +
 87.1040 +	/* High Hat (verified on real YM3812) */
 87.1041 +	env = volume_calc(SLOT7_1);
 87.1042 +	if( env < ENV_QUIET )
 87.1043 +	{
 87.1044 +
 87.1045 +		/* high hat phase generation:
 87.1046 +            phase = d0 or 234 (based on frequency only)
 87.1047 +            phase = 34 or 2d0 (based on noise)
 87.1048 +        */
 87.1049 +
 87.1050 +		/* base frequency derived from operator 1 in channel 7 */
 87.1051 +		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
 87.1052 +		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
 87.1053 +		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
 87.1054 +
 87.1055 +		unsigned char res1 = (bit2 ^ bit7) | bit3;
 87.1056 +
 87.1057 +		/* when res1 = 0 phase = 0x000 | 0xd0; */
 87.1058 +		/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
 87.1059 +		UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
 87.1060 +
 87.1061 +		/* enable gate based on frequency of operator 2 in channel 8 */
 87.1062 +		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
 87.1063 +		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
 87.1064 +
 87.1065 +		unsigned char res2 = (bit3e ^ bit5e);
 87.1066 +
 87.1067 +		/* when res2 = 0 pass the phase from calculation above (res1); */
 87.1068 +		/* when res2 = 1 phase = 0x200 | (0xd0>>2); */
 87.1069 +		if (res2)
 87.1070 +			phase = (0x200|(0xd0>>2));
 87.1071 +
 87.1072 +
 87.1073 +		/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
 87.1074 +		/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
 87.1075 +		if (phase&0x200)
 87.1076 +		{
 87.1077 +			if (noise)
 87.1078 +				phase = 0x200|0xd0;
 87.1079 +		}
 87.1080 +		else
 87.1081 +		/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
 87.1082 +		/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
 87.1083 +		{
 87.1084 +			if (noise)
 87.1085 +				phase = 0xd0>>2;
 87.1086 +		}
 87.1087 +
 87.1088 +		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
 87.1089 +	}
 87.1090 +
 87.1091 +	/* Snare Drum (verified on real YM3812) */
 87.1092 +	env = volume_calc(SLOT7_2);
 87.1093 +	if( env < ENV_QUIET )
 87.1094 +	{
 87.1095 +		/* base frequency derived from operator 1 in channel 7 */
 87.1096 +		unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
 87.1097 +
 87.1098 +		/* when bit8 = 0 phase = 0x100; */
 87.1099 +		/* when bit8 = 1 phase = 0x200; */
 87.1100 +		UINT32 phase = bit8 ? 0x200 : 0x100;
 87.1101 +
 87.1102 +		/* Noise bit XOR'es phase by 0x100 */
 87.1103 +		/* when noisebit = 0 pass the phase from calculation above */
 87.1104 +		/* when noisebit = 1 phase ^= 0x100; */
 87.1105 +		/* in other words: phase ^= (noisebit<<8); */
 87.1106 +		if (noise)
 87.1107 +			phase ^= 0x100;
 87.1108 +
 87.1109 +		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
 87.1110 +	}
 87.1111 +
 87.1112 +	/* Tom Tom (verified on real YM3812) */
 87.1113 +	env = volume_calc(SLOT8_1);
 87.1114 +	if( env < ENV_QUIET )
 87.1115 +		output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;
 87.1116 +
 87.1117 +	/* Top Cymbal (verified on real YM3812) */
 87.1118 +	env = volume_calc(SLOT8_2);
 87.1119 +	if( env < ENV_QUIET )
 87.1120 +	{
 87.1121 +		/* base frequency derived from operator 1 in channel 7 */
 87.1122 +		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
 87.1123 +		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
 87.1124 +		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
 87.1125 +
 87.1126 +		unsigned char res1 = (bit2 ^ bit7) | bit3;
 87.1127 +
 87.1128 +		/* when res1 = 0 phase = 0x000 | 0x100; */
 87.1129 +		/* when res1 = 1 phase = 0x200 | 0x100; */
 87.1130 +		UINT32 phase = res1 ? 0x300 : 0x100;
 87.1131 +
 87.1132 +		/* enable gate based on frequency of operator 2 in channel 8 */
 87.1133 +		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
 87.1134 +		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
 87.1135 +
 87.1136 +		unsigned char res2 = (bit3e ^ bit5e);
 87.1137 +		/* when res2 = 0 pass the phase from calculation above (res1); */
 87.1138 +		/* when res2 = 1 phase = 0x200 | 0x100; */
 87.1139 +		if (res2)
 87.1140 +			phase = 0x300;
 87.1141 +
 87.1142 +		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
 87.1143 +	}
 87.1144 +
 87.1145 +}
 87.1146 +
 87.1147 +
 87.1148 +/* generic table initialize */
 87.1149 +static int init_tables(void)
 87.1150 +{
 87.1151 +	signed int i,x;
 87.1152 +	signed int n;
 87.1153 +	double o,m;
 87.1154 +
 87.1155 +
 87.1156 +	for (x=0; x<TL_RES_LEN; x++)
 87.1157 +	{
 87.1158 +		m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
 87.1159 +		m = floor(m);
 87.1160 +
 87.1161 +		/* we never reach (1<<16) here due to the (x+1) */
 87.1162 +		/* result fits within 16 bits at maximum */
 87.1163 +
 87.1164 +		n = (int)m;		/* 16 bits here */
 87.1165 +		n >>= 4;		/* 12 bits here */
 87.1166 +		if (n&1)		/* round to nearest */
 87.1167 +			n = (n>>1)+1;
 87.1168 +		else
 87.1169 +			n = n>>1;
 87.1170 +						/* 11 bits here (rounded) */
 87.1171 +		n <<= 1;		/* 12 bits here (as in real chip) */
 87.1172 +		tl_tab[ x*2 + 0 ] = n;
 87.1173 +		tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
 87.1174 +
 87.1175 +		for (i=1; i<12; i++)
 87.1176 +		{
 87.1177 +			tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;
 87.1178 +			tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
 87.1179 +		}
 87.1180 +	#if 0
 87.1181 +			logerror("tl %04i", x*2);
 87.1182 +			for (i=0; i<12; i++)
 87.1183 +				logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );
 87.1184 +			logerror("\n");
 87.1185 +	#endif
 87.1186 +	}
 87.1187 +	/*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
 87.1188 +
 87.1189 +
 87.1190 +	for (i=0; i<SIN_LEN; i++)
 87.1191 +	{
 87.1192 +		/* non-standard sinus */
 87.1193 +		m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
 87.1194 +
 87.1195 +		/* we never reach zero here due to ((i*2)+1) */
 87.1196 +
 87.1197 +		if (m>0.0)
 87.1198 +			o = 8*log(1.0/m)/log(2.0);	/* convert to 'decibels' */
 87.1199 +		else
 87.1200 +			o = 8*log(-1.0/m)/log(2.0);	/* convert to 'decibels' */
 87.1201 +
 87.1202 +		o = o / (ENV_STEP/4);
 87.1203 +
 87.1204 +		n = (int)(2.0*o);
 87.1205 +		if (n&1)						/* round to nearest */
 87.1206 +			n = (n>>1)+1;
 87.1207 +		else
 87.1208 +			n = n>>1;
 87.1209 +
 87.1210 +		sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
 87.1211 +
 87.1212 +		/*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
 87.1213 +	}
 87.1214 +
 87.1215 +	for (i=0; i<SIN_LEN; i++)
 87.1216 +	{
 87.1217 +		/* waveform 1:  __      __     */
 87.1218 +		/*             /  \____/  \____*/
 87.1219 +		/* output only first half of the sinus waveform (positive one) */
 87.1220 +
 87.1221 +		if (i & (1<<(SIN_BITS-1)) )
 87.1222 +			sin_tab[1*SIN_LEN+i] = TL_TAB_LEN;
 87.1223 +		else
 87.1224 +			sin_tab[1*SIN_LEN+i] = sin_tab[i];
 87.1225 +
 87.1226 +		/* waveform 2:  __  __  __  __ */
 87.1227 +		/*             /  \/  \/  \/  \*/
 87.1228 +		/* abs(sin) */
 87.1229 +
 87.1230 +		sin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];
 87.1231 +
 87.1232 +		/* waveform 3:  _   _   _   _  */
 87.1233 +		/*             / |_/ |_/ |_/ |_*/
 87.1234 +		/* abs(output only first quarter of the sinus waveform) */
 87.1235 +
 87.1236 +		if (i & (1<<(SIN_BITS-2)) )
 87.1237 +			sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;
 87.1238 +		else
 87.1239 +			sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];
 87.1240 +
 87.1241 +		/*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );
 87.1242 +        logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );
 87.1243 +        logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/
 87.1244 +	}
 87.1245 +	/*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/
 87.1246 +
 87.1247 +
 87.1248 +#ifdef SAVE_SAMPLE
 87.1249 +	sample[0]=fopen("sampsum.pcm","wb");
 87.1250 +#endif
 87.1251 +
 87.1252 +	return 1;
 87.1253 +}
 87.1254 +
 87.1255 +static void OPLCloseTable( void )
 87.1256 +{
 87.1257 +#ifdef SAVE_SAMPLE
 87.1258 +	fclose(sample[0]);
 87.1259 +#endif
 87.1260 +}
 87.1261 +
 87.1262 +
 87.1263 +
 87.1264 +static void OPL_initalize(FM_OPL *OPL)
 87.1265 +{
 87.1266 +	int i;
 87.1267 +
 87.1268 +	/* frequency base */
 87.1269 +	OPL->freqbase  = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate  : 0;
 87.1270 +#if 0
 87.1271 +	OPL->rate = (double)OPL->clock / 72.0;
 87.1272 +	OPL->freqbase  = 1.0;
 87.1273 +#endif
 87.1274 +
 87.1275 +	/*logerror("freqbase=%f\n", OPL->freqbase);*/
 87.1276 +
 87.1277 +	/* Timer base time */
 87.1278 +	OPL->TimerBase = attotime_mul(ATTOTIME_IN_HZ(OPL->clock), 72);
 87.1279 +
 87.1280 +	/* make fnumber -> increment counter table */
 87.1281 +	for( i=0 ; i < 1024 ; i++ )
 87.1282 +	{
 87.1283 +		/* opn phase increment counter = 20bit */
 87.1284 +		OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
 87.1285 +#if 0
 87.1286 +		logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",
 87.1287 +				 i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );
 87.1288 +#endif
 87.1289 +	}
 87.1290 +
 87.1291 +#if 0
 87.1292 +	for( i=0 ; i < 16 ; i++ )
 87.1293 +	{
 87.1294 +		logerror("FMOPL.C: sl_tab[%i] = %08x\n",
 87.1295 +			i, sl_tab[i] );
 87.1296 +	}
 87.1297 +	for( i=0 ; i < 8 ; i++ )
 87.1298 +	{
 87.1299 +		int j;
 87.1300 +		logerror("FMOPL.C: ksl_tab[oct=%2i] =",i);
 87.1301 +		for (j=0; j<16; j++)
 87.1302 +		{
 87.1303 +			logerror("%08x ", ksl_tab[i*16+j] );
 87.1304 +		}
 87.1305 +		logerror("\n");
 87.1306 +	}
 87.1307 +#endif
 87.1308 +
 87.1309 +
 87.1310 +	/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
 87.1311 +	/* One entry from LFO_AM_TABLE lasts for 64 samples */
 87.1312 +	OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;
 87.1313 +
 87.1314 +	/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
 87.1315 +	OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;
 87.1316 +
 87.1317 +	/*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
 87.1318 +
 87.1319 +	/* Noise generator: a step takes 1 sample */
 87.1320 +	OPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;
 87.1321 +
 87.1322 +	OPL->eg_timer_add  = (1<<EG_SH)  * OPL->freqbase;
 87.1323 +	OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
 87.1324 +	/*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/
 87.1325 +
 87.1326 +}
 87.1327 +
 87.1328 +INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
 87.1329 +{
 87.1330 +	if( !SLOT->key )
 87.1331 +	{
 87.1332 +		/* restart Phase Generator */
 87.1333 +		SLOT->Cnt = 0;
 87.1334 +		/* phase -> Attack */
 87.1335 +		SLOT->state = EG_ATT;
 87.1336 +	}
 87.1337 +	SLOT->key |= key_set;
 87.1338 +}
 87.1339 +
 87.1340 +INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
 87.1341 +{
 87.1342 +	if( SLOT->key )
 87.1343 +	{
 87.1344 +		SLOT->key &= key_clr;
 87.1345 +
 87.1346 +		if( !SLOT->key )
 87.1347 +		{
 87.1348 +			/* phase -> Release */
 87.1349 +			if (SLOT->state>EG_REL)
 87.1350 +				SLOT->state = EG_REL;
 87.1351 +		}
 87.1352 +	}
 87.1353 +}
 87.1354 +
 87.1355 +/* update phase increment counter of operator (also update the EG rates if necessary) */
 87.1356 +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
 87.1357 +{
 87.1358 +	int ksr;
 87.1359 +
 87.1360 +	/* (frequency) phase increment counter */
 87.1361 +	SLOT->Incr = CH->fc * SLOT->mul;
 87.1362 +	ksr = CH->kcode >> SLOT->KSR;
 87.1363 +
 87.1364 +	if( SLOT->ksr != ksr )
 87.1365 +	{
 87.1366 +		SLOT->ksr = ksr;
 87.1367 +
 87.1368 +		/* calculate envelope generator rates */
 87.1369 +		if ((SLOT->ar + SLOT->ksr) < 16+62)
 87.1370 +		{
 87.1371 +			SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
 87.1372 +			SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
 87.1373 +		}
 87.1374 +		else
 87.1375 +		{
 87.1376 +			SLOT->eg_sh_ar  = 0;
 87.1377 +			SLOT->eg_sel_ar = 13*RATE_STEPS;
 87.1378 +		}
 87.1379 +		SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
 87.1380 +		SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
 87.1381 +		SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
 87.1382 +		SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
 87.1383 +	}
 87.1384 +}
 87.1385 +
 87.1386 +/* set multi,am,vib,EG-TYP,KSR,mul */
 87.1387 +INLINE void set_mul(FM_OPL *OPL,int slot,int v)
 87.1388 +{
 87.1389 +	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 87.1390 +	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
 87.1391 +
 87.1392 +	SLOT->mul     = mul_tab[v&0x0f];
 87.1393 +	SLOT->KSR     = (v&0x10) ? 0 : 2;
 87.1394 +	SLOT->eg_type = (v&0x20);
 87.1395 +	SLOT->vib     = (v&0x40);
 87.1396 +	SLOT->AMmask  = (v&0x80) ? ~0 : 0;
 87.1397 +	CALC_FCSLOT(CH,SLOT);
 87.1398 +}
 87.1399 +
 87.1400 +/* set ksl & tl */
 87.1401 +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
 87.1402 +{
 87.1403 +	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 87.1404 +	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
 87.1405 +	int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
 87.1406 +
 87.1407 +	SLOT->ksl = ksl ? 3-ksl : 31;
 87.1408 +	SLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
 87.1409 +
 87.1410 +	SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 87.1411 +}
 87.1412 +
 87.1413 +/* set attack rate & decay rate  */
 87.1414 +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
 87.1415 +{
 87.1416 +	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 87.1417 +	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
 87.1418 +
 87.1419 +	SLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;
 87.1420 +
 87.1421 +	if ((SLOT->ar + SLOT->ksr) < 16+62)
 87.1422 +	{
 87.1423 +		SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
 87.1424 +		SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
 87.1425 +	}
 87.1426 +	else
 87.1427 +	{
 87.1428 +		SLOT->eg_sh_ar  = 0;
 87.1429 +		SLOT->eg_sel_ar = 13*RATE_STEPS;
 87.1430 +	}
 87.1431 +
 87.1432 +	SLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
 87.1433 +	SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
 87.1434 +	SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
 87.1435 +}
 87.1436 +
 87.1437 +/* set sustain level & release rate */
 87.1438 +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
 87.1439 +{
 87.1440 +	OPL_CH   *CH   = &OPL->P_CH[slot/2];
 87.1441 +	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
 87.1442 +
 87.1443 +	SLOT->sl  = sl_tab[ v>>4 ];
 87.1444 +
 87.1445 +	SLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
 87.1446 +	SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
 87.1447 +	SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
 87.1448 +}
 87.1449 +
 87.1450 +
 87.1451 +/* write a value v to register r on OPL chip */
 87.1452 +static void OPLWriteReg(FM_OPL *OPL, int r, int v)
 87.1453 +{
 87.1454 +	OPL_CH *CH;
 87.1455 +	int slot;
 87.1456 +	int block_fnum;
 87.1457 +
 87.1458 +
 87.1459 +	/* adjust bus to 8 bits */
 87.1460 +	r &= 0xff;
 87.1461 +	v &= 0xff;
 87.1462 +
 87.1463 +	if (LOG_CYM_FILE && (cymfile) && (r!=0) )
 87.1464 +	{
 87.1465 +		fputc( (unsigned char)r, cymfile );
 87.1466 +		fputc( (unsigned char)v, cymfile );
 87.1467 +	}
 87.1468 +
 87.1469 +
 87.1470 +	switch(r&0xe0)
 87.1471 +	{
 87.1472 +	case 0x00:	/* 00-1f:control */
 87.1473 +		switch(r&0x1f)
 87.1474 +		{
 87.1475 +		case 0x01:	/* waveform select enable */
 87.1476 +			if(OPL->type&OPL_TYPE_WAVESEL)
 87.1477 +			{
 87.1478 +				OPL->wavesel = v&0x20;
 87.1479 +				/* do not change the waveform previously selected */
 87.1480 +			}
 87.1481 +			break;
 87.1482 +		case 0x02:	/* Timer 1 */
 87.1483 +			OPL->T[0] = (256-v)*4;
 87.1484 +			break;
 87.1485 +		case 0x03:	/* Timer 2 */
 87.1486 +			OPL->T[1] = (256-v)*16;
 87.1487 +			break;
 87.1488 +		case 0x04:	/* IRQ clear / mask and Timer enable */
 87.1489 +			if(v&0x80)
 87.1490 +			{	/* IRQ flag clear */
 87.1491 +				OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */
 87.1492 +			}
 87.1493 +			else
 87.1494 +			{	/* set IRQ mask ,timer enable*/
 87.1495 +				UINT8 st1 = v&1;
 87.1496 +				UINT8 st2 = (v>>1)&1;
 87.1497 +
 87.1498 +				/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
 87.1499 +				OPL_STATUS_RESET(OPL, v & (0x78-0x08) );
 87.1500 +				OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );
 87.1501 +
 87.1502 +				/* timer 2 */
 87.1503 +				if(OPL->st[1] != st2)
 87.1504 +				{
 87.1505 +					attotime period = st2 ? attotime_mul(OPL->TimerBase, OPL->T[1]) : attotime_zero;
 87.1506 +					OPL->st[1] = st2;
 87.1507 +					if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);
 87.1508 +				}
 87.1509 +				/* timer 1 */
 87.1510 +				if(OPL->st[0] != st1)
 87.1511 +				{
 87.1512 +					attotime period = st1 ? attotime_mul(OPL->TimerBase, OPL->T[0]) : attotime_zero;
 87.1513 +					OPL->st[0] = st1;
 87.1514 +					if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);
 87.1515 +				}
 87.1516 +			}
 87.1517 +			break;
 87.1518 +#if BUILD_Y8950
 87.1519 +		case 0x06:		/* Key Board OUT */
 87.1520 +			if(OPL->type&OPL_TYPE_KEYBOARD)
 87.1521 +			{
 87.1522 +				if(OPL->keyboardhandler_w)
 87.1523 +					OPL->keyboardhandler_w(OPL->keyboard_param,v);
 87.1524 +				else
 87.1525 +					logerror("Y8950: write unmapped KEYBOARD port\n");
 87.1526 +			}
 87.1527 +			break;
 87.1528 +		case 0x07:	/* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
 87.1529 +			if(OPL->type&OPL_TYPE_ADPCM)
 87.1530 +				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
 87.1531 +			break;
 87.1532 +#endif
 87.1533 +		case 0x08:	/* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
 87.1534 +			OPL->mode = v;
 87.1535 +#if BUILD_Y8950
 87.1536 +			if(OPL->type&OPL_TYPE_ADPCM)
 87.1537 +				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */
 87.1538 +#endif
 87.1539 +			break;
 87.1540 +
 87.1541 +#if BUILD_Y8950
 87.1542 +		case 0x09:		/* START ADD */
 87.1543 +		case 0x0a:
 87.1544 +		case 0x0b:		/* STOP ADD  */
 87.1545 +		case 0x0c:
 87.1546 +		case 0x0d:		/* PRESCALE   */
 87.1547 +		case 0x0e:
 87.1548 +		case 0x0f:		/* ADPCM data write */
 87.1549 +		case 0x10:		/* DELTA-N    */
 87.1550 +		case 0x11:		/* DELTA-N    */
 87.1551 +		case 0x12:		/* ADPCM volume */
 87.1552 +			if(OPL->type&OPL_TYPE_ADPCM)
 87.1553 +				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
 87.1554 +			break;
 87.1555 +
 87.1556 +		case 0x15:		/* DAC data high 8 bits (F7,F6...F2) */
 87.1557 +		case 0x16:		/* DAC data low 2 bits (F1, F0 in bits 7,6) */
 87.1558 +		case 0x17:		/* DAC data shift (S2,S1,S0 in bits 2,1,0) */
 87.1559 +			logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);
 87.1560 +			break;
 87.1561 +
 87.1562 +		case 0x18:		/* I/O CTRL (Direction) */
 87.1563 +			if(OPL->type&OPL_TYPE_IO)
 87.1564 +				OPL->portDirection = v&0x0f;
 87.1565 +			break;
 87.1566 +		case 0x19:		/* I/O DATA */
 87.1567 +			if(OPL->type&OPL_TYPE_IO)
 87.1568 +			{
 87.1569 +				OPL->portLatch = v;
 87.1570 +				if(OPL->porthandler_w)
 87.1571 +					OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
 87.1572 +			}
 87.1573 +			break;
 87.1574 +#endif
 87.1575 +		default:
 87.1576 +			pclog("FMOPL.C: write to unknown register: %02x\n",r);
 87.1577 +			break;
 87.1578 +		}
 87.1579 +		break;
 87.1580 +	case 0x20:	/* am ON, vib ON, ksr, eg_type, mul */
 87.1581 +		slot = slot_array[r&0x1f];
 87.1582 +		if(slot < 0) return;
 87.1583 +		set_mul(OPL,slot,v);
 87.1584 +		break;
 87.1585 +	case 0x40:
 87.1586 +		slot = slot_array[r&0x1f];
 87.1587 +		if(slot < 0) return;
 87.1588 +		set_ksl_tl(OPL,slot,v);
 87.1589 +		break;
 87.1590 +	case 0x60:
 87.1591 +		slot = slot_array[r&0x1f];
 87.1592 +		if(slot < 0) return;
 87.1593 +		set_ar_dr(OPL,slot,v);
 87.1594 +		break;
 87.1595 +	case 0x80:
 87.1596 +		slot = slot_array[r&0x1f];
 87.1597 +		if(slot < 0) return;
 87.1598 +		set_sl_rr(OPL,slot,v);
 87.1599 +		break;
 87.1600 +	case 0xa0:
 87.1601 +		if (r == 0xbd)			/* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
 87.1602 +		{
 87.1603 +			OPL->lfo_am_depth = v & 0x80;
 87.1604 +			OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
 87.1605 +
 87.1606 +			OPL->rhythm  = v&0x3f;
 87.1607 +
 87.1608 +			if(OPL->rhythm&0x20)
 87.1609 +			{
 87.1610 +				/* BD key on/off */
 87.1611 +				if(v&0x10)
 87.1612 +				{
 87.1613 +					FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);
 87.1614 +					FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);
 87.1615 +				}
 87.1616 +				else
 87.1617 +				{
 87.1618 +					FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
 87.1619 +					FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
 87.1620 +				}
 87.1621 +				/* HH key on/off */
 87.1622 +				if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);
 87.1623 +				else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
 87.1624 +				/* SD key on/off */
 87.1625 +				if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);
 87.1626 +				else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
 87.1627 +				/* TOM key on/off */
 87.1628 +				if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);
 87.1629 +				else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
 87.1630 +				/* TOP-CY key on/off */
 87.1631 +				if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);
 87.1632 +				else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
 87.1633 +			}
 87.1634 +			else
 87.1635 +			{
 87.1636 +				/* BD key off */
 87.1637 +				FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
 87.1638 +				FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
 87.1639 +				/* HH key off */
 87.1640 +				FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
 87.1641 +				/* SD key off */
 87.1642 +				FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
 87.1643 +				/* TOM key off */
 87.1644 +				FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
 87.1645 +				/* TOP-CY off */
 87.1646 +				FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
 87.1647 +			}
 87.1648 +			return;
 87.1649 +		}
 87.1650 +		/* keyon,block,fnum */
 87.1651 +		if( (r&0x0f) > 8) return;
 87.1652 +		CH = &OPL->P_CH[r&0x0f];
 87.1653 +		if(!(r&0x10))
 87.1654 +		{	/* a0-a8 */
 87.1655 +			block_fnum  = (CH->block_fnum&0x1f00) | v;
 87.1656 +		}
 87.1657 +		else
 87.1658 +		{	/* b0-b8 */
 87.1659 +			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
 87.1660 +
 87.1661 +			if(v&0x20)
 87.1662 +			{
 87.1663 +				FM_KEYON (&CH->SLOT[SLOT1], 1);
 87.1664 +				FM_KEYON (&CH->SLOT[SLOT2], 1);
 87.1665 +			}
 87.1666 +			else
 87.1667 +			{
 87.1668 +				FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 87.1669 +				FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 87.1670 +			}
 87.1671 +		}
 87.1672 +		/* update */
 87.1673 +		if(CH->block_fnum != block_fnum)
 87.1674 +		{
 87.1675 +			UINT8 block  = block_fnum >> 10;
 87.1676 +
 87.1677 +			CH->block_fnum = block_fnum;
 87.1678 +
 87.1679 +			CH->ksl_base = ksl_tab[block_fnum>>6];
 87.1680 +			CH->fc       = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);
 87.1681 +
 87.1682 +			/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
 87.1683 +			CH->kcode    = (CH->block_fnum&0x1c00)>>9;
 87.1684 +
 87.1685 +			 /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */
 87.1686 +			/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */
 87.1687 +			/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
 87.1688 +			if (OPL->mode&0x40)
 87.1689 +				CH->kcode |= (CH->block_fnum&0x100)>>8;	/* notesel == 1 */
 87.1690 +			else
 87.1691 +				CH->kcode |= (CH->block_fnum&0x200)>>9;	/* notesel == 0 */
 87.1692 +
 87.1693 +			/* refresh Total Level in both SLOTs of this channel */
 87.1694 +			CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 87.1695 +			CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 87.1696 +
 87.1697 +			/* refresh frequency counter in both SLOTs of this channel */
 87.1698 +			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 87.1699 +			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 87.1700 +		}
 87.1701 +		break;
 87.1702 +	case 0xc0:
 87.1703 +		/* FB,C */
 87.1704 +		if( (r&0x0f) > 8) return;
 87.1705 +		CH = &OPL->P_CH[r&0x0f];
 87.1706 +		CH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
 87.1707 +		CH->SLOT[SLOT1].CON = v&1;
 87.1708 +		CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation;
 87.1709 +		break;
 87.1710 +	case 0xe0: /* waveform select */
 87.1711 +		/* simply ignore write to the waveform select register if selecting not enabled in test register */
 87.1712 +		if(OPL->wavesel)
 87.1713 +		{
 87.1714 +			slot = slot_array[r&0x1f];
 87.1715 +			if(slot < 0) return;
 87.1716 +			CH = &OPL->P_CH[slot/2];
 87.1717 +
 87.1718 +			CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;
 87.1719 +		}
 87.1720 +		break;
 87.1721 +	}
 87.1722 +}
 87.1723 +
 87.1724 +static TIMER_CALLBACK( cymfile_callback )
 87.1725 +{
 87.1726 +	if (cymfile)
 87.1727 +	{
 87.1728 +		fputc( (unsigned char)0, cymfile );
 87.1729 +	}
 87.1730 +}
 87.1731 +
 87.1732 +/* lock/unlock for common table */
 87.1733 +static int OPL_LockTable(running_device *device)
 87.1734 +{
 87.1735 +	num_lock++;
 87.1736 +	if(num_lock>1) return 0;
 87.1737 +
 87.1738 +	/* first time */
 87.1739 +
 87.1740 +	cur_chip = NULL;
 87.1741 +	/* allocate total level table (128kb space) */
 87.1742 +	if( !init_tables() )
 87.1743 +	{
 87.1744 +		num_lock--;
 87.1745 +		return -1;
 87.1746 +	}
 87.1747 +
 87.1748 +		#if 0
 87.1749 +	if (LOG_CYM_FILE)
 87.1750 +	{
 87.1751 +		cymfile = fopen("3812_.cym","wb");
 87.1752 +		if (cymfile)
 87.1753 +			timer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); /*110 Hz pulse timer*/
 87.1754 +		else
 87.1755 +			logerror("Could not create file 3812_.cym\n");
 87.1756 +	}
 87.1757 +                #endif
 87.1758 +	return 0;
 87.1759 +}
 87.1760 +
 87.1761 +static void OPL_UnLockTable(void)
 87.1762 +{
 87.1763 +	if(num_lock) num_lock--;
 87.1764 +	if(num_lock) return;
 87.1765 +
 87.1766 +	/* last time */
 87.1767 +
 87.1768 +	cur_chip = NULL;
 87.1769 +	OPLCloseTable();
 87.1770 +        #if 0
 87.1771 +	if (cymfile)
 87.1772 +		fclose (cymfile);
 87.1773 +	cymfile = NULL;
 87.1774 +	#endif
 87.1775 +}
 87.1776 +
 87.1777 +static void OPLResetChip(FM_OPL *OPL)
 87.1778 +{
 87.1779 +	int c,s;
 87.1780 +	int i;
 87.1781 +
 87.1782 +	OPL->eg_timer = 0;
 87.1783 +	OPL->eg_cnt   = 0;
 87.1784 +
 87.1785 +	OPL->noise_rng = 1;	/* noise shift register */
 87.1786 +	OPL->mode   = 0;	/* normal mode */
 87.1787 +	OPL_STATUS_RESET(OPL,0x7f);
 87.1788 +
 87.1789 +	/* reset with register write */
 87.1790 +	OPLWriteReg(OPL,0x01,0); /* wavesel disable */
 87.1791 +	OPLWriteReg(OPL,0x02,0); /* Timer1 */
 87.1792 +	OPLWriteReg(OPL,0x03,0); /* Timer2 */
 87.1793 +	OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
 87.1794 +	for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
 87.1795 +
 87.1796 +	/* reset operator parameters */
 87.1797 +	for( c = 0 ; c < 9 ; c++ )
 87.1798 +	{
 87.1799 +		OPL_CH *CH = &OPL->P_CH[c];
 87.1800 +		for(s = 0 ; s < 2 ; s++ )
 87.1801 +		{
 87.1802 +			/* wave table */
 87.1803 +			CH->SLOT[s].wavetable = 0;
 87.1804 +			CH->SLOT[s].state     = EG_OFF;
 87.1805 +			CH->SLOT[s].volume    = MAX_ATT_INDEX;
 87.1806 +		}
 87.1807 +	}
 87.1808 +#if BUILD_Y8950
 87.1809 +	if(OPL->type&OPL_TYPE_ADPCM)
 87.1810 +	{
 87.1811 +		YM_DELTAT *DELTAT = OPL->deltat;
 87.1812 +
 87.1813 +		DELTAT->freqbase = OPL->freqbase;
 87.1814 +		DELTAT->output_pointer = &output_deltat[0];
 87.1815 +		DELTAT->portshift = 5;
 87.1816 +		DELTAT->output_range = 1<<23;
 87.1817 +		YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);
 87.1818 +	}
 87.1819 +#endif
 87.1820 +}
 87.1821 +
 87.1822 +#if 0
 87.1823 +static STATE_POSTLOAD( OPL_postload )
 87.1824 +{
 87.1825 +	FM_OPL *OPL = (FM_OPL *)param;
 87.1826 +	int slot, ch;
 87.1827 +
 87.1828 +	for( ch=0 ; ch < 9 ; ch++ )
 87.1829 +	{
 87.1830 +		OPL_CH *CH = &OPL->P_CH[ch];
 87.1831 +
 87.1832 +		/* Look up key scale level */
 87.1833 +		UINT32 block_fnum = CH->block_fnum;
 87.1834 +		CH->ksl_base = ksl_tab[block_fnum >> 6];
 87.1835 +		CH->fc       = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));
 87.1836 +
 87.1837 +		for( slot=0 ; slot < 2 ; slot++ )
 87.1838 +		{
 87.1839 +			OPL_SLOT *SLOT = &CH->SLOT[slot];
 87.1840 +
 87.1841 +			/* Calculate key scale rate */
 87.1842 +			SLOT->ksr = CH->kcode >> SLOT->KSR;
 87.1843 +
 87.1844 +			/* Calculate attack, decay and release rates */
 87.1845 +			if ((SLOT->ar + SLOT->ksr) < 16+62)
 87.1846 +			{
 87.1847 +				SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
 87.1848 +				SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
 87.1849 +			}
 87.1850 +			else
 87.1851 +			{
 87.1852 +				SLOT->eg_sh_ar  = 0;
 87.1853 +				SLOT->eg_sel_ar = 13*RATE_STEPS;
 87.1854 +			}
 87.1855 +			SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
 87.1856 +			SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
 87.1857 +			SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
 87.1858 +			SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
 87.1859 +
 87.1860 +			/* Calculate phase increment */
 87.1861 +			SLOT->Incr = CH->fc * SLOT->mul;
 87.1862 +
 87.1863 +			/* Total level */
 87.1864 +			SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
 87.1865 +
 87.1866 +			/* Connect output */
 87.1867 +			SLOT->connect1 = SLOT->CON ? &output[0] : &phase_modulation;
 87.1868 +		}
 87.1869 +	}
 87.1870 +#if BUILD_Y8950
 87.1871 +	if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
 87.1872 +	{
 87.1873 +		// We really should call the postlod function for the YM_DELTAT, but it's hard without registers
 87.1874 +		// (see the way the YM2610 does it)
 87.1875 +		//YM_DELTAT_postload(OPL->deltat, REGS);
 87.1876 +	}
 87.1877 +#endif
 87.1878 +}
 87.1879 +
 87.1880 +
 87.1881 +static void OPLsave_state_channel(running_device *device, OPL_CH *CH)
 87.1882 +{
 87.1883 +	int slot, ch;
 87.1884 +
 87.1885 +	for( ch=0 ; ch < 9 ; ch++, CH++ )
 87.1886 +	{
 87.1887 +		/* channel */
 87.1888 +		state_save_register_device_item(device, ch, CH->block_fnum);
 87.1889 +		state_save_register_device_item(device, ch, CH->kcode);
 87.1890 +		/* slots */
 87.1891 +		for( slot=0 ; slot < 2 ; slot++ )
 87.1892 +		{
 87.1893 +			OPL_SLOT *SLOT = &CH->SLOT[slot];
 87.1894 +
 87.1895 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->ar);
 87.1896 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->dr);
 87.1897 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->rr);
 87.1898 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->KSR);
 87.1899 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->ksl);
 87.1900 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->mul);
 87.1901 +
 87.1902 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->Cnt);
 87.1903 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->FB);
 87.1904 +			state_save_register_device_item_array(device, ch * 2 + slot, SLOT->op1_out);
 87.1905 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->CON);
 87.1906 +
 87.1907 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->eg_type);
 87.1908 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->state);
 87.1909 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->TL);
 87.1910 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->volume);
 87.1911 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->sl);
 87.1912 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->key);
 87.1913 +
 87.1914 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->AMmask);
 87.1915 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->vib);
 87.1916 +
 87.1917 +			state_save_register_device_item(device, ch * 2 + slot, SLOT->wavetable);
 87.1918 +		}
 87.1919 +	}
 87.1920 +}
 87.1921 +
 87.1922 +
 87.1923 +/* Register savestate for a virtual YM3812/YM3526Y8950 */
 87.1924 +
 87.1925 +static void OPL_save_state(FM_OPL *OPL, running_device *device)
 87.1926 +{
 87.1927 +	OPLsave_state_channel(device, OPL->P_CH);
 87.1928 +
 87.1929 +	state_save_register_device_item(device, 0, OPL->eg_cnt);
 87.1930 +	state_save_register_device_item(device, 0, OPL->eg_timer);
 87.1931 +
 87.1932 +	state_save_register_device_item(device, 0, OPL->rhythm);
 87.1933 +
 87.1934 +	state_save_register_device_item(device, 0, OPL->lfo_am_depth);
 87.1935 +	state_save_register_device_item(device, 0, OPL->lfo_pm_depth_range);
 87.1936 +	state_save_register_device_item(device, 0, OPL->lfo_am_cnt);
 87.1937 +	state_save_register_device_item(device, 0, OPL->lfo_pm_cnt);
 87.1938 +
 87.1939 +	state_save_register_device_item(device, 0, OPL->noise_rng);
 87.1940 +	state_save_register_device_item(device, 0, OPL->noise_p);
 87.1941 +
 87.1942 +	if( OPL->type & OPL_TYPE_WAVESEL )
 87.1943 +	{
 87.1944 +		state_save_register_device_item(device, 0, OPL->wavesel);
 87.1945 +	}
 87.1946 +
 87.1947 +	state_save_register_device_item_array(device, 0, OPL->T);
 87.1948 +	state_save_register_device_item_array(device, 0, OPL->st);
 87.1949 +
 87.1950 +#if BUILD_Y8950
 87.1951 +	if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
 87.1952 +	{
 87.1953 +		YM_DELTAT_savestate(device, OPL->deltat);
 87.1954 +	}
 87.1955 +
 87.1956 +	if ( OPL->type & OPL_TYPE_IO )
 87.1957 +	{
 87.1958 +		state_save_register_device_item(device, 0, OPL->portDirection);
 87.1959 +		state_save_register_device_item(device, 0, OPL->portLatch);
 87.1960 +	}
 87.1961 +#endif
 87.1962 +
 87.1963 +	state_save_register_device_item(device, 0, OPL->address);
 87.1964 +	state_save_register_device_item(device, 0, OPL->status);
 87.1965 +	state_save_register_device_item(device, 0, OPL->statusmask);
 87.1966 +	state_save_register_device_item(device, 0, OPL->mode);
 87.1967 +
 87.1968 +	state_save_register_postload(device->machine, OPL_postload, OPL);
 87.1969 +}
 87.1970 +#endif
 87.1971 +
 87.1972 +/* Create one of virtual YM3812/YM3526/Y8950 */
 87.1973 +/* 'clock' is chip clock in Hz  */
 87.1974 +/* 'rate'  is sampling rate  */
 87.1975 +static FM_OPL *OPLCreate(running_device *device, UINT32 clock, UINT32 rate, int type)
 87.1976 +{
 87.1977 +	char *ptr;
 87.1978 +	FM_OPL *OPL;
 87.1979 +	int state_size;
 87.1980 +
 87.1981 +	if (OPL_LockTable(device) == -1) return NULL;
 87.1982 +
 87.1983 +	/* calculate OPL state size */
 87.1984 +	state_size  = sizeof(FM_OPL);
 87.1985 +
 87.1986 +#if BUILD_Y8950
 87.1987 +	if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
 87.1988 +#endif
 87.1989 +
 87.1990 +	/* allocate memory block */
 87.1991 +	ptr = (char *)malloc(state_size); //auto_alloc_array_clear(device->machine, UINT8, state_size);
 87.1992 +        memset(ptr,0,state_size);
 87.1993 +	OPL  = (FM_OPL *)ptr;
 87.1994 +
 87.1995 +	ptr += sizeof(FM_OPL);
 87.1996 +
 87.1997 +#if BUILD_Y8950
 87.1998 +	if (type&OPL_TYPE_ADPCM)
 87.1999 +	{
 87.2000 +		OPL->deltat = (YM_DELTAT *)ptr;
 87.2001 +	}
 87.2002 +	ptr += sizeof(YM_DELTAT);
 87.2003 +#endif
 87.2004 +
 87.2005 +	OPL->device = device;
 87.2006 +	OPL->type  = type;
 87.2007 +	OPL->clock = clock;
 87.2008 +	OPL->rate  = rate;
 87.2009 +
 87.2010 +	/* init global tables */
 87.2011 +	OPL_initalize(OPL);
 87.2012 +
 87.2013 +	return OPL;
 87.2014 +}
 87.2015 +
 87.2016 +/* Destroy one of virtual YM3812 */
 87.2017 +static void OPLDestroy(FM_OPL *OPL)
 87.2018 +{
 87.2019 +	OPL_UnLockTable();
 87.2020 +	free(OPL);
 87.2021 +//	auto_free(OPL->device->machine, OPL);
 87.2022 +}
 87.2023 +
 87.2024 +/* Optional handlers */
 87.2025 +
 87.2026 +static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)
 87.2027 +{
 87.2028 +	OPL->timer_handler   = timer_handler;
 87.2029 +	OPL->TimerParam = param;
 87.2030 +}
 87.2031 +static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)
 87.2032 +{
 87.2033 +	OPL->IRQHandler     = IRQHandler;
 87.2034 +	OPL->IRQParam = param;
 87.2035 +}
 87.2036 +static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)
 87.2037 +{
 87.2038 +	OPL->UpdateHandler = UpdateHandler;
 87.2039 +	OPL->UpdateParam = param;
 87.2040 +}
 87.2041 +
 87.2042 +static int OPLWrite(FM_OPL *OPL,int a,int v)
 87.2043 +{
 87.2044 +	if( !(a&1) )
 87.2045 +	{	/* address port */
 87.2046 +		OPL->address = v & 0xff;
 87.2047 +	}
 87.2048 +	else
 87.2049 +	{	/* data port */
 87.2050 +		if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
 87.2051 +		OPLWriteReg(OPL,OPL->address,v);
 87.2052 +	}
 87.2053 +	return OPL->status>>7;
 87.2054 +}
 87.2055 +
 87.2056 +static unsigned char OPLRead(FM_OPL *OPL,int a)
 87.2057 +{
 87.2058 +	if( !(a&1) )
 87.2059 +	{
 87.2060 +		/* status port */
 87.2061 +
 87.2062 +		#if BUILD_Y8950
 87.2063 +
 87.2064 +		if(OPL->type&OPL_TYPE_ADPCM)	/* Y8950 */
 87.2065 +		{
 87.2066 +			return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1);
 87.2067 +		}
 87.2068 +
 87.2069 +		#endif
 87.2070 +
 87.2071 +		/* OPL and OPL2 */
 87.2072 +		return OPL->status & (OPL->statusmask|0x80);
 87.2073 +	}
 87.2074 +
 87.2075 +#if BUILD_Y8950
 87.2076 +	/* data port */
 87.2077 +	switch(OPL->address)
 87.2078 +	{
 87.2079 +	case 0x05: /* KeyBoard IN */
 87.2080 +		if(OPL->type&OPL_TYPE_KEYBOARD)
 87.2081 +		{
 87.2082 +			if(OPL->keyboardhandler_r)
 87.2083 +				return OPL->keyboardhandler_r(OPL->keyboard_param);
 87.2084 +			else
 87.2085 +				logerror("Y8950: read unmapped KEYBOARD port\n");
 87.2086 +		}
 87.2087 +		return 0;
 87.2088 +
 87.2089 +	case 0x0f: /* ADPCM-DATA  */
 87.2090 +		if(OPL->type&OPL_TYPE_ADPCM)
 87.2091 +		{
 87.2092 +			UINT8 val;
 87.2093 +
 87.2094 +			val = YM_DELTAT_ADPCM_Read(OPL->deltat);
 87.2095 +			/*logerror("Y8950: read ADPCM value read=%02x\n",val);*/
 87.2096 +			return val;
 87.2097 +		}
 87.2098 +		return 0;
 87.2099 +
 87.2100 +	case 0x19: /* I/O DATA    */
 87.2101 +		if(OPL->type&OPL_TYPE_IO)
 87.2102 +		{
 87.2103 +			if(OPL->porthandler_r)
 87.2104 +				return OPL->porthandler_r(OPL->port_param);
 87.2105 +			else
 87.2106 +				logerror("Y8950:read unmapped I/O port\n");
 87.2107 +		}
 87.2108 +		return 0;
 87.2109 +	case 0x1a: /* PCM-DATA    */
 87.2110 +		if(OPL->type&OPL_TYPE_ADPCM)
 87.2111 +		{
 87.2112 +			logerror("Y8950 A/D convertion is accessed but not implemented !\n");
 87.2113 +			return 0x80; /* 2's complement PCM data - result from A/D convertion */
 87.2114 +		}
 87.2115 +		return 0;
 87.2116 +	}
 87.2117 +#endif
 87.2118 +
 87.2119 +	return 0xff;
 87.2120 +}
 87.2121 +
 87.2122 +/* CSM Key Controll */
 87.2123 +INLINE void CSMKeyControll(OPL_CH *CH)
 87.2124 +{
 87.2125 +	FM_KEYON (&CH->SLOT[SLOT1], 4);
 87.2126 +	FM_KEYON (&CH->SLOT[SLOT2], 4);
 87.2127 +
 87.2128 +	/* The key off should happen exactly one sample later - not implemented correctly yet */
 87.2129 +
 87.2130 +	FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
 87.2131 +	FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
 87.2132 +}
 87.2133 +
 87.2134 +
 87.2135 +static int OPLTimerOver(FM_OPL *OPL,int c)
 87.2136 +{
 87.2137 +	if( c )
 87.2138 +	{	/* Timer B */
 87.2139 +		OPL_STATUS_SET(OPL,0x20);
 87.2140 +	}
 87.2141 +	else
 87.2142 +	{	/* Timer A */
 87.2143 +		OPL_STATUS_SET(OPL,0x40);
 87.2144 +		/* CSM mode key,TL controll */
 87.2145 +		if( OPL->mode & 0x80 )
 87.2146 +		{	/* CSM mode total level latch and auto key on */
 87.2147 +			int ch;
 87.2148 +			if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
 87.2149 +			for(ch=0; ch<9; ch++)
 87.2150 +				CSMKeyControll( &OPL->P_CH[ch] );
 87.2151 +		}
 87.2152 +	}
 87.2153 +	/* reload timer */
 87.2154 +	if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,attotime_mul(OPL->TimerBase, OPL->T[c]));
 87.2155 +	return OPL->status>>7;
 87.2156 +}
 87.2157 +
 87.2158 +
 87.2159 +#define MAX_OPL_CHIPS 2
 87.2160 +
 87.2161 +
 87.2162 +#if (BUILD_YM3812)
 87.2163 +
 87.2164 +void * ym3812_init(running_device *device, UINT32 clock, UINT32 rate)
 87.2165 +{
 87.2166 +	/* emulator create */
 87.2167 +	FM_OPL *YM3812 = OPLCreate(device,clock,rate,OPL_TYPE_YM3812);
 87.2168 +	if (YM3812)
 87.2169 +	{
 87.2170 +//		OPL_save_state(YM3812, device);
 87.2171 +		ym3812_reset_chip(YM3812);
 87.2172 +	}
 87.2173 +	return YM3812;
 87.2174 +}
 87.2175 +
 87.2176 +void ym3812_shutdown(void *chip)
 87.2177 +{
 87.2178 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2179 +
 87.2180 +	/* emulator shutdown */
 87.2181 +	OPLDestroy(YM3812);
 87.2182 +}
 87.2183 +void ym3812_reset_chip(void *chip)
 87.2184 +{
 87.2185 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2186 +	OPLResetChip(YM3812);
 87.2187 +}
 87.2188 +
 87.2189 +int ym3812_write(void *chip, int a, int v)
 87.2190 +{
 87.2191 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2192 +	return OPLWrite(YM3812, a, v);
 87.2193 +}
 87.2194 +
 87.2195 +unsigned char ym3812_read(void *chip, int a)
 87.2196 +{
 87.2197 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2198 +	/* YM3812 always returns bit2 and bit1 in HIGH state */
 87.2199 +	return OPLRead(YM3812, a) | 0x06 ;
 87.2200 +}
 87.2201 +int ym3812_timer_over(void *chip, int c)
 87.2202 +{
 87.2203 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2204 +	return OPLTimerOver(YM3812, c);
 87.2205 +}
 87.2206 +
 87.2207 +void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
 87.2208 +{
 87.2209 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2210 +	OPLSetTimerHandler(YM3812, timer_handler, param);
 87.2211 +}
 87.2212 +void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
 87.2213 +{
 87.2214 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2215 +	OPLSetIRQHandler(YM3812, IRQHandler, param);
 87.2216 +}
 87.2217 +void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
 87.2218 +{
 87.2219 +	FM_OPL *YM3812 = (FM_OPL *)chip;
 87.2220 +	OPLSetUpdateHandler(YM3812, UpdateHandler, param);
 87.2221 +}
 87.2222 +
 87.2223 +
 87.2224 +/*
 87.2225 +** Generate samples for one of the YM3812's
 87.2226 +**
 87.2227 +** 'which' is the virtual YM3812 number
 87.2228 +** '*buffer' is the output buffer pointer
 87.2229 +** 'length' is the number of samples that should be generated
 87.2230 +*/
 87.2231 +void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
 87.2232 +{
 87.2233 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2234 +	UINT8		rhythm = OPL->rhythm&0x20;
 87.2235 +	OPLSAMPLE	*buf = buffer;
 87.2236 +	int i;
 87.2237 +
 87.2238 +	if( (void *)OPL != cur_chip ){
 87.2239 +		cur_chip = (void *)OPL;
 87.2240 +		/* rhythm slots */
 87.2241 +		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
 87.2242 +		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
 87.2243 +		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
 87.2244 +		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
 87.2245 +	}
 87.2246 +	for( i=0; i < length ; i++ )
 87.2247 +	{
 87.2248 +		int lt;
 87.2249 +
 87.2250 +		output[0] = 0;
 87.2251 +
 87.2252 +		advance_lfo(OPL);
 87.2253 +
 87.2254 +		/* FM part */
 87.2255 +		OPL_CALC_CH(&OPL->P_CH[0]);
 87.2256 +		OPL_CALC_CH(&OPL->P_CH[1]);
 87.2257 +		OPL_CALC_CH(&OPL->P_CH[2]);
 87.2258 +		OPL_CALC_CH(&OPL->P_CH[3]);
 87.2259 +		OPL_CALC_CH(&OPL->P_CH[4]);
 87.2260 +		OPL_CALC_CH(&OPL->P_CH[5]);
 87.2261 +
 87.2262 +		if(!rhythm)
 87.2263 +		{
 87.2264 +			OPL_CALC_CH(&OPL->P_CH[6]);
 87.2265 +			OPL_CALC_CH(&OPL->P_CH[7]);
 87.2266 +			OPL_CALC_CH(&OPL->P_CH[8]);
 87.2267 +		}
 87.2268 +		else		/* Rhythm part */
 87.2269 +		{
 87.2270 +			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
 87.2271 +		}
 87.2272 +
 87.2273 +		lt = output[0];
 87.2274 +
 87.2275 +		lt >>= FINAL_SH;
 87.2276 +
 87.2277 +		/* limit check */
 87.2278 +		lt = limit( lt , MAXOUT, MINOUT );
 87.2279 +
 87.2280 +		#ifdef SAVE_SAMPLE
 87.2281 +		if (which==0)
 87.2282 +		{
 87.2283 +			SAVE_ALL_CHANNELS
 87.2284 +		}
 87.2285 +		#endif
 87.2286 +
 87.2287 +		/* store to sound buffer */
 87.2288 +		buf[i] = lt;
 87.2289 +
 87.2290 +		advance(OPL);
 87.2291 +	}
 87.2292 +
 87.2293 +}
 87.2294 +#endif /* BUILD_YM3812 */
 87.2295 +
 87.2296 +
 87.2297 +
 87.2298 +#if (BUILD_YM3526)
 87.2299 +
 87.2300 +void *ym3526_init(running_device *device, UINT32 clock, UINT32 rate)
 87.2301 +{
 87.2302 +	/* emulator create */
 87.2303 +	FM_OPL *YM3526 = OPLCreate(device,clock,rate,OPL_TYPE_YM3526);
 87.2304 +	if (YM3526)
 87.2305 +	{
 87.2306 +		OPL_save_state(YM3526, device);
 87.2307 +		ym3526_reset_chip(YM3526);
 87.2308 +	}
 87.2309 +	return YM3526;
 87.2310 +}
 87.2311 +
 87.2312 +void ym3526_shutdown(void *chip)
 87.2313 +{
 87.2314 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2315 +	/* emulator shutdown */
 87.2316 +	OPLDestroy(YM3526);
 87.2317 +}
 87.2318 +void ym3526_reset_chip(void *chip)
 87.2319 +{
 87.2320 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2321 +	OPLResetChip(YM3526);
 87.2322 +}
 87.2323 +
 87.2324 +int ym3526_write(void *chip, int a, int v)
 87.2325 +{
 87.2326 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2327 +	return OPLWrite(YM3526, a, v);
 87.2328 +}
 87.2329 +
 87.2330 +unsigned char ym3526_read(void *chip, int a)
 87.2331 +{
 87.2332 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2333 +	/* YM3526 always returns bit2 and bit1 in HIGH state */
 87.2334 +	return OPLRead(YM3526, a) | 0x06 ;
 87.2335 +}
 87.2336 +int ym3526_timer_over(void *chip, int c)
 87.2337 +{
 87.2338 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2339 +	return OPLTimerOver(YM3526, c);
 87.2340 +}
 87.2341 +
 87.2342 +void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
 87.2343 +{
 87.2344 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2345 +	OPLSetTimerHandler(YM3526, timer_handler, param);
 87.2346 +}
 87.2347 +void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
 87.2348 +{
 87.2349 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2350 +	OPLSetIRQHandler(YM3526, IRQHandler, param);
 87.2351 +}
 87.2352 +void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
 87.2353 +{
 87.2354 +	FM_OPL *YM3526 = (FM_OPL *)chip;
 87.2355 +	OPLSetUpdateHandler(YM3526, UpdateHandler, param);
 87.2356 +}
 87.2357 +
 87.2358 +
 87.2359 +/*
 87.2360 +** Generate samples for one of the YM3526's
 87.2361 +**
 87.2362 +** 'which' is the virtual YM3526 number
 87.2363 +** '*buffer' is the output buffer pointer
 87.2364 +** 'length' is the number of samples that should be generated
 87.2365 +*/
 87.2366 +void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
 87.2367 +{
 87.2368 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2369 +	UINT8		rhythm = OPL->rhythm&0x20;
 87.2370 +	OPLSAMPLE	*buf = buffer;
 87.2371 +	int i;
 87.2372 +
 87.2373 +	if( (void *)OPL != cur_chip ){
 87.2374 +		cur_chip = (void *)OPL;
 87.2375 +		/* rhythm slots */
 87.2376 +		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
 87.2377 +		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
 87.2378 +		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
 87.2379 +		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
 87.2380 +	}
 87.2381 +	for( i=0; i < length ; i++ )
 87.2382 +	{
 87.2383 +		int lt;
 87.2384 +
 87.2385 +		output[0] = 0;
 87.2386 +
 87.2387 +		advance_lfo(OPL);
 87.2388 +
 87.2389 +		/* FM part */
 87.2390 +		OPL_CALC_CH(&OPL->P_CH[0]);
 87.2391 +		OPL_CALC_CH(&OPL->P_CH[1]);
 87.2392 +		OPL_CALC_CH(&OPL->P_CH[2]);
 87.2393 +		OPL_CALC_CH(&OPL->P_CH[3]);
 87.2394 +		OPL_CALC_CH(&OPL->P_CH[4]);
 87.2395 +		OPL_CALC_CH(&OPL->P_CH[5]);
 87.2396 +
 87.2397 +		if(!rhythm)
 87.2398 +		{
 87.2399 +			OPL_CALC_CH(&OPL->P_CH[6]);
 87.2400 +			OPL_CALC_CH(&OPL->P_CH[7]);
 87.2401 +			OPL_CALC_CH(&OPL->P_CH[8]);
 87.2402 +		}
 87.2403 +		else		/* Rhythm part */
 87.2404 +		{
 87.2405 +			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
 87.2406 +		}
 87.2407 +
 87.2408 +		lt = output[0];
 87.2409 +
 87.2410 +		lt >>= FINAL_SH;
 87.2411 +
 87.2412 +		/* limit check */
 87.2413 +		lt = limit( lt , MAXOUT, MINOUT );
 87.2414 +
 87.2415 +		#ifdef SAVE_SAMPLE
 87.2416 +		if (which==0)
 87.2417 +		{
 87.2418 +			SAVE_ALL_CHANNELS
 87.2419 +		}
 87.2420 +		#endif
 87.2421 +
 87.2422 +		/* store to sound buffer */
 87.2423 +		buf[i] = lt;
 87.2424 +
 87.2425 +		advance(OPL);
 87.2426 +	}
 87.2427 +
 87.2428 +}
 87.2429 +#endif /* BUILD_YM3526 */
 87.2430 +
 87.2431 +
 87.2432 +
 87.2433 +
 87.2434 +#if BUILD_Y8950
 87.2435 +
 87.2436 +static void Y8950_deltat_status_set(void *chip, UINT8 changebits)
 87.2437 +{
 87.2438 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2439 +	OPL_STATUS_SET(Y8950, changebits);
 87.2440 +}
 87.2441 +static void Y8950_deltat_status_reset(void *chip, UINT8 changebits)
 87.2442 +{
 87.2443 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2444 +	OPL_STATUS_RESET(Y8950, changebits);
 87.2445 +}
 87.2446 +
 87.2447 +void *y8950_init(running_device *device, UINT32 clock, UINT32 rate)
 87.2448 +{
 87.2449 +	/* emulator create */
 87.2450 +	FM_OPL *Y8950 = OPLCreate(device,clock,rate,OPL_TYPE_Y8950);
 87.2451 +	if (Y8950)
 87.2452 +	{
 87.2453 +		Y8950->deltat->status_set_handler = Y8950_deltat_status_set;
 87.2454 +		Y8950->deltat->status_reset_handler = Y8950_deltat_status_reset;
 87.2455 +		Y8950->deltat->status_change_which_chip = Y8950;
 87.2456 +		Y8950->deltat->status_change_EOS_bit = 0x10;		/* status flag: set bit4 on End Of Sample */
 87.2457 +		Y8950->deltat->status_change_BRDY_bit = 0x08;	/* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */
 87.2458 +
 87.2459 +		/*Y8950->deltat->write_time = 10.0 / clock;*/		/* a single byte write takes 10 cycles of main clock */
 87.2460 +		/*Y8950->deltat->read_time  = 8.0 / clock;*/		/* a single byte read takes 8 cycles of main clock */
 87.2461 +		/* reset */
 87.2462 +		OPL_save_state(Y8950, device);
 87.2463 +		y8950_reset_chip(Y8950);
 87.2464 +	}
 87.2465 +
 87.2466 +	return Y8950;
 87.2467 +}
 87.2468 +
 87.2469 +void y8950_shutdown(void *chip)
 87.2470 +{
 87.2471 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2472 +	/* emulator shutdown */
 87.2473 +	OPLDestroy(Y8950);
 87.2474 +}
 87.2475 +void y8950_reset_chip(void *chip)
 87.2476 +{
 87.2477 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2478 +	OPLResetChip(Y8950);
 87.2479 +}
 87.2480 +
 87.2481 +int y8950_write(void *chip, int a, int v)
 87.2482 +{
 87.2483 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2484 +	return OPLWrite(Y8950, a, v);
 87.2485 +}
 87.2486 +
 87.2487 +unsigned char y8950_read(void *chip, int a)
 87.2488 +{
 87.2489 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2490 +	return OPLRead(Y8950, a);
 87.2491 +}
 87.2492 +int y8950_timer_over(void *chip, int c)
 87.2493 +{
 87.2494 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2495 +	return OPLTimerOver(Y8950, c);
 87.2496 +}
 87.2497 +
 87.2498 +void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
 87.2499 +{
 87.2500 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2501 +	OPLSetTimerHandler(Y8950, timer_handler, param);
 87.2502 +}
 87.2503 +void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
 87.2504 +{
 87.2505 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2506 +	OPLSetIRQHandler(Y8950, IRQHandler, param);
 87.2507 +}
 87.2508 +void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
 87.2509 +{
 87.2510 +	FM_OPL *Y8950 = (FM_OPL *)chip;
 87.2511 +	OPLSetUpdateHandler(Y8950, UpdateHandler, param);
 87.2512 +}
 87.2513 +
 87.2514 +void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )
 87.2515 +{
 87.2516 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2517 +	OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr);
 87.2518 +	OPL->deltat->memory_size = deltat_mem_size;
 87.2519 +}
 87.2520 +
 87.2521 +/*
 87.2522 +** Generate samples for one of the Y8950's
 87.2523 +**
 87.2524 +** 'which' is the virtual Y8950 number
 87.2525 +** '*buffer' is the output buffer pointer
 87.2526 +** 'length' is the number of samples that should be generated
 87.2527 +*/
 87.2528 +void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
 87.2529 +{
 87.2530 +	int i;
 87.2531 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2532 +	UINT8		rhythm  = OPL->rhythm&0x20;
 87.2533 +	YM_DELTAT	*DELTAT = OPL->deltat;
 87.2534 +	OPLSAMPLE	*buf    = buffer;
 87.2535 +
 87.2536 +	if( (void *)OPL != cur_chip ){
 87.2537 +		cur_chip = (void *)OPL;
 87.2538 +		/* rhythm slots */
 87.2539 +		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
 87.2540 +		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
 87.2541 +		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
 87.2542 +		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
 87.2543 +
 87.2544 +	}
 87.2545 +	for( i=0; i < length ; i++ )
 87.2546 +	{
 87.2547 +		int lt;
 87.2548 +
 87.2549 +		output[0] = 0;
 87.2550 +		output_deltat[0] = 0;
 87.2551 +
 87.2552 +		advance_lfo(OPL);
 87.2553 +
 87.2554 +		/* deltaT ADPCM */
 87.2555 +		if( DELTAT->portstate&0x80 )
 87.2556 +			YM_DELTAT_ADPCM_CALC(DELTAT);
 87.2557 +
 87.2558 +		/* FM part */
 87.2559 +		OPL_CALC_CH(&OPL->P_CH[0]);
 87.2560 +		OPL_CALC_CH(&OPL->P_CH[1]);
 87.2561 +		OPL_CALC_CH(&OPL->P_CH[2]);
 87.2562 +		OPL_CALC_CH(&OPL->P_CH[3]);
 87.2563 +		OPL_CALC_CH(&OPL->P_CH[4]);
 87.2564 +		OPL_CALC_CH(&OPL->P_CH[5]);
 87.2565 +
 87.2566 +		if(!rhythm)
 87.2567 +		{
 87.2568 +			OPL_CALC_CH(&OPL->P_CH[6]);
 87.2569 +			OPL_CALC_CH(&OPL->P_CH[7]);
 87.2570 +			OPL_CALC_CH(&OPL->P_CH[8]);
 87.2571 +		}
 87.2572 +		else		/* Rhythm part */
 87.2573 +		{
 87.2574 +			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
 87.2575 +		}
 87.2576 +
 87.2577 +		lt = output[0] + (output_deltat[0]>>11);
 87.2578 +
 87.2579 +		lt >>= FINAL_SH;
 87.2580 +
 87.2581 +		/* limit check */
 87.2582 +		lt = limit( lt , MAXOUT, MINOUT );
 87.2583 +
 87.2584 +		#ifdef SAVE_SAMPLE
 87.2585 +		if (which==0)
 87.2586 +		{
 87.2587 +			SAVE_ALL_CHANNELS
 87.2588 +		}
 87.2589 +		#endif
 87.2590 +
 87.2591 +		/* store to sound buffer */
 87.2592 +		buf[i] = lt;
 87.2593 +
 87.2594 +		advance(OPL);
 87.2595 +	}
 87.2596 +
 87.2597 +}
 87.2598 +
 87.2599 +void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)
 87.2600 +{
 87.2601 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2602 +	OPL->porthandler_w = PortHandler_w;
 87.2603 +	OPL->porthandler_r = PortHandler_r;
 87.2604 +	OPL->port_param = param;
 87.2605 +}
 87.2606 +
 87.2607 +void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)
 87.2608 +{
 87.2609 +	FM_OPL		*OPL = (FM_OPL *)chip;
 87.2610 +	OPL->keyboardhandler_w = KeyboardHandler_w;
 87.2611 +	OPL->keyboardhandler_r = KeyboardHandler_r;
 87.2612 +	OPL->keyboard_param = param;
 87.2613 +}
 87.2614 +
 87.2615 +#endif
 87.2616 +
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/src/mame/fmopl.h	Sun Apr 21 14:54:35 2013 +0100
    88.3 @@ -0,0 +1,126 @@
    88.4 +#pragma once
    88.5 +
    88.6 +#ifndef __FMOPL_H__
    88.7 +#define __FMOPL_H__
    88.8 +
    88.9 +#ifndef STUFF
   88.10 +#define STUFF
   88.11 +typedef int64_t attotime;
   88.12 +#define ATTOTIME_IN_HZ(x) (1000000000/(x))
   88.13 +#define attotime_mul(x,y) ((x)*(y))
   88.14 +#define attotime_to_double(x) ((double)(x)/1000000000.0)
   88.15 +#define attotime_zero 0
   88.16 +
   88.17 +#define running_device void
   88.18 +#define INLINE static
   88.19 +//#define M_PI 3.142
   88.20 +#endif
   88.21 +
   88.22 +/* --- select emulation chips --- */
   88.23 +#define BUILD_YM3812 (1)
   88.24 +#define BUILD_YM3526 (0)
   88.25 +#define BUILD_Y8950  (0)
   88.26 +
   88.27 +/* select output bits size of output : 8 or 16 */
   88.28 +#define OPL_SAMPLE_BITS 16
   88.29 +
   88.30 +/* compiler dependence */
   88.31 +#ifndef __OSDCOMM_H__
   88.32 +#define __OSDCOMM_H__
   88.33 +typedef unsigned char	UINT8;   /* unsigned  8bit */
   88.34 +typedef unsigned short	UINT16;  /* unsigned 16bit */
   88.35 +typedef unsigned int	UINT32;  /* unsigned 32bit */
   88.36 +typedef signed char		INT8;    /* signed  8bit   */
   88.37 +typedef signed short	INT16;   /* signed 16bit   */
   88.38 +typedef signed int		INT32;   /* signed 32bit   */
   88.39 +#endif /* __OSDCOMM_H__ */
   88.40 +
   88.41 +typedef signed short OPLSAMPLE;
   88.42 +/*
   88.43 +#if (OPL_SAMPLE_BITS==16)
   88.44 +typedef INT16 OPLSAMPLE;
   88.45 +#endif
   88.46 +#if (OPL_SAMPLE_BITS==8)
   88.47 +typedef INT8 OPLSAMPLE;
   88.48 +#endif
   88.49 +*/
   88.50 +
   88.51 +typedef void (*OPL_TIMERHANDLER)(void *param,int timer,attotime period);
   88.52 +typedef void (*OPL_IRQHANDLER)(void *param,int irq);
   88.53 +typedef void (*OPL_UPDATEHANDLER)(void *param,int min_interval_us);
   88.54 +typedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);
   88.55 +typedef unsigned char (*OPL_PORTHANDLER_R)(void *param);
   88.56 +
   88.57 +
   88.58 +#if BUILD_YM3812
   88.59 +
   88.60 +void *ym3812_init(running_device *device, UINT32 clock, UINT32 rate);
   88.61 +void ym3812_shutdown(void *chip);
   88.62 +void ym3812_reset_chip(void *chip);
   88.63 +int  ym3812_write(void *chip, int a, int v);
   88.64 +unsigned char ym3812_read(void *chip, int a);
   88.65 +int  ym3812_timer_over(void *chip, int c);
   88.66 +void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length);
   88.67 +
   88.68 +void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
   88.69 +void ym3812_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
   88.70 +void ym3812_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
   88.71 +
   88.72 +#endif /* BUILD_YM3812 */
   88.73 +
   88.74 +
   88.75 +#if BUILD_YM3526
   88.76 +
   88.77 +/*
   88.78 +** Initialize YM3526 emulator(s).
   88.79 +**
   88.80 +** 'num' is the number of virtual YM3526's to allocate
   88.81 +** 'clock' is the chip clock in Hz
   88.82 +** 'rate' is sampling rate
   88.83 +*/
   88.84 +void *ym3526_init(running_device *device, UINT32 clock, UINT32 rate);
   88.85 +/* shutdown the YM3526 emulators*/
   88.86 +void ym3526_shutdown(void *chip);
   88.87 +void ym3526_reset_chip(void *chip);
   88.88 +int  ym3526_write(void *chip, int a, int v);
   88.89 +unsigned char ym3526_read(void *chip, int a);
   88.90 +int  ym3526_timer_over(void *chip, int c);
   88.91 +/*
   88.92 +** Generate samples for one of the YM3526's
   88.93 +**
   88.94 +** 'which' is the virtual YM3526 number
   88.95 +** '*buffer' is the output buffer pointer
   88.96 +** 'length' is the number of samples that should be generated
   88.97 +*/
   88.98 +void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length);
   88.99 +
  88.100 +void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
  88.101 +void ym3526_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
  88.102 +void ym3526_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
  88.103 +
  88.104 +#endif /* BUILD_YM3526 */
  88.105 +
  88.106 +
  88.107 +#if BUILD_Y8950
  88.108 +
  88.109 +/* Y8950 port handlers */
  88.110 +void y8950_set_port_handler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);
  88.111 +void y8950_set_keyboard_handler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);
  88.112 +void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );
  88.113 +
  88.114 +void * y8950_init(running_device *device, UINT32 clock, UINT32 rate);
  88.115 +void y8950_shutdown(void *chip);
  88.116 +void y8950_reset_chip(void *chip);
  88.117 +int  y8950_write(void *chip, int a, int v);
  88.118 +unsigned char y8950_read (void *chip, int a);
  88.119 +int  y8950_timer_over(void *chip, int c);
  88.120 +void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length);
  88.121 +
  88.122 +void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
  88.123 +void y8950_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
  88.124 +void y8950_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
  88.125 +
  88.126 +#endif /* BUILD_Y8950 */
  88.127 +
  88.128 +
  88.129 +#endif /* __FMOPL_H__ */
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/src/mame/ymf262.c	Sun Apr 21 14:54:35 2013 +0100
    89.3 @@ -0,0 +1,2730 @@
    89.4 +/*
    89.5 +**
    89.6 +** File: ymf262.c - software implementation of YMF262
    89.7 +**                  FM sound generator type OPL3
    89.8 +**
    89.9 +** Copyright Jarek Burczynski
   89.10 +**
   89.11 +** Version 0.2
   89.12 +**
   89.13 +
   89.14 +Revision History:
   89.15 +
   89.16 +03-03-2003: initial release
   89.17 + - thanks to Olivier Galibert and Chris Hardy for YMF262 and YAC512 chips
   89.18 + - thanks to Stiletto for the datasheets
   89.19 +
   89.20 +   Features as listed in 4MF262A6 data sheet:
   89.21 +    1. Registers are compatible with YM3812 (OPL2) FM sound source.
   89.22 +    2. Up to six sounds can be used as four-operator melody sounds for variety.
   89.23 +    3. 18 simultaneous melody sounds, or 15 melody sounds with 5 rhythm sounds (with two operators).
   89.24 +    4. 6 four-operator melody sounds and 6 two-operator melody sounds, or 6 four-operator melody
   89.25 +       sounds, 3 two-operator melody sounds and 5 rhythm sounds (with four operators).
   89.26 +    5. 8 selectable waveforms.
   89.27 +    6. 4-channel sound output.
   89.28 +    7. YMF262 compabile DAC (YAC512) is available.
   89.29 +    8. LFO for vibrato and tremolo effedts.
   89.30 +    9. 2 programable timers.
   89.31 +   10. Shorter register access time compared with YM3812.
   89.32 +   11. 5V single supply silicon gate CMOS process.
   89.33 +   12. 24 Pin SOP Package (YMF262-M), 48 Pin SQFP Package (YMF262-S).
   89.34 +
   89.35 +
   89.36 +differences between OPL2 and OPL3 not documented in Yamaha datahasheets:
   89.37 +- sinus table is a little different: the negative part is off by one...
   89.38 +
   89.39 +- in order to enable selection of four different waveforms on OPL2
   89.40 +  one must set bit 5 in register 0x01(test).
   89.41 +  on OPL3 this bit is ignored and 4-waveform select works *always*.
   89.42 +  (Don't confuse this with OPL3's 8-waveform select.)
   89.43 +
   89.44 +- Envelope Generator: all 15 x rates take zero time on OPL3
   89.45 +  (on OPL2 15 0 and 15 1 rates take some time while 15 2 and 15 3 rates
   89.46 +  take zero time)
   89.47 +
   89.48 +- channel calculations: output of operator 1 is in perfect sync with
   89.49 +  output of operator 2 on OPL3; on OPL and OPL2 output of operator 1
   89.50 +  is always delayed by one sample compared to output of operator 2
   89.51 +
   89.52 +
   89.53 +differences between OPL2 and OPL3 shown in datasheets:
   89.54 +- YMF262 does not support CSM mode
   89.55 +
   89.56 +
   89.57 +*/
   89.58 +
   89.59 +#include <stdio.h>
   89.60 +#include <stdint.h>
   89.61 +#include <math.h>
   89.62 +#include <string.h>
   89.63 +#include <stdlib.h>
   89.64 +//#include "emu.h"
   89.65 +#include "ymf262.h"
   89.66 +
   89.67 +
   89.68 +
   89.69 +/* output final shift */
   89.70 +#if (OPL3_SAMPLE_BITS==16)
   89.71 +	#define FINAL_SH	(0)
   89.72 +	#define MAXOUT		(+32767)
   89.73 +	#define MINOUT		(-32768)
   89.74 +#else
   89.75 +	#define FINAL_SH	(8)
   89.76 +	#define MAXOUT		(+127)
   89.77 +	#define MINOUT		(-128)
   89.78 +#endif
   89.79 +
   89.80 +
   89.81 +#define FREQ_SH			16  /* 16.16 fixed point (frequency calculations) */
   89.82 +#define EG_SH			16  /* 16.16 fixed point (EG timing)              */
   89.83 +#define LFO_SH			24  /*  8.24 fixed point (LFO calculations)       */
   89.84 +#define TIMER_SH		16  /* 16.16 fixed point (timers calculations)    */
   89.85 +
   89.86 +#define FREQ_MASK		((1<<FREQ_SH)-1)
   89.87 +
   89.88 +/* envelope output entries */
   89.89 +#define ENV_BITS		10
   89.90 +#define ENV_LEN			(1<<ENV_BITS)
   89.91 +#define ENV_STEP		(128.0/ENV_LEN)
   89.92 +
   89.93 +#define MAX_ATT_INDEX	((1<<(ENV_BITS-1))-1) /*511*/
   89.94 +#define MIN_ATT_INDEX	(0)
   89.95 +
   89.96 +/* sinwave entries */
   89.97 +#define SIN_BITS		10
   89.98 +#define SIN_LEN			(1<<SIN_BITS)
   89.99 +#define SIN_MASK		(SIN_LEN-1)
  89.100 +
  89.101 +#define TL_RES_LEN		(256)	/* 8 bits addressing (real chip) */
  89.102 +
  89.103 +
  89.104 +
  89.105 +/* register number to channel number , slot offset */
  89.106 +#define SLOT1 0
  89.107 +#define SLOT2 1
  89.108 +
  89.109 +/* Envelope Generator phases */
  89.110 +
  89.111 +#define EG_ATT			4
  89.112 +#define EG_DEC			3
  89.113 +#define EG_SUS			2
  89.114 +#define EG_REL			1
  89.115 +#define EG_OFF			0
  89.116 +
  89.117 +
  89.118 +/* save output as raw 16-bit sample */
  89.119 +
  89.120 +/*#define SAVE_SAMPLE*/
  89.121 +
  89.122 +#ifdef SAVE_SAMPLE
  89.123 +static FILE *sample[1];
  89.124 +	#if 1	/*save to MONO file */
  89.125 +		#define SAVE_ALL_CHANNELS \
  89.126 +		{	signed int pom = a; \
  89.127 +			fputc((unsigned short)pom&0xff,sample[0]); \
  89.128 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  89.129 +		}
  89.130 +	#else	/*save to STEREO file */
  89.131 +		#define SAVE_ALL_CHANNELS \
  89.132 +		{	signed int pom = a; \
  89.133 +			fputc((unsigned short)pom&0xff,sample[0]); \
  89.134 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  89.135 +			pom = b; \
  89.136 +			fputc((unsigned short)pom&0xff,sample[0]); \
  89.137 +			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
  89.138 +		}
  89.139 +	#endif
  89.140 +#endif
  89.141 +
  89.142 +#define LOG_CYM_FILE 0
  89.143 +static FILE * cymfile = NULL;
  89.144 +
  89.145 +
  89.146 +
  89.147 +
  89.148 +
  89.149 +#define OPL3_TYPE_YMF262 (0)	/* 36 operators, 8 waveforms */
  89.150 +
  89.151 +
  89.152 +typedef struct{
  89.153 +	UINT32	ar;			/* attack rate: AR<<2           */
  89.154 +	UINT32	dr;			/* decay rate:  DR<<2           */
  89.155 +	UINT32	rr;			/* release rate:RR<<2           */
  89.156 +	UINT8	KSR;		/* key scale rate               */
  89.157 +	UINT8	ksl;		/* keyscale level               */
  89.158 +	UINT8	ksr;		/* key scale rate: kcode>>KSR   */
  89.159 +	UINT8	mul;		/* multiple: mul_tab[ML]        */
  89.160 +
  89.161 +	/* Phase Generator */
  89.162 +	UINT32	Cnt;		/* frequency counter            */
  89.163 +	UINT32	Incr;		/* frequency counter step       */
  89.164 +	UINT8   FB;			/* feedback shift value         */
  89.165 +	INT32   *connect;	/* slot output pointer          */
  89.166 +	INT32   op1_out[2];	/* slot1 output for feedback    */
  89.167 +	UINT8   CON;		/* connection (algorithm) type  */
  89.168 +
  89.169 +	/* Envelope Generator */
  89.170 +	UINT8	eg_type;	/* percussive/non-percussive mode */
  89.171 +	UINT8	state;		/* phase type                   */
  89.172 +	UINT32	TL;			/* total level: TL << 2         */
  89.173 +	INT32	TLL;		/* adjusted now TL              */
  89.174 +	INT32	volume;		/* envelope counter             */
  89.175 +	UINT32	sl;			/* sustain level: sl_tab[SL]    */
  89.176 +
  89.177 +	UINT32	eg_m_ar;	/* (attack state)               */
  89.178 +	UINT8	eg_sh_ar;	/* (attack state)               */
  89.179 +	UINT8	eg_sel_ar;	/* (attack state)               */
  89.180 +	UINT32	eg_m_dr;	/* (decay state)                */
  89.181 +	UINT8	eg_sh_dr;	/* (decay state)                */
  89.182 +	UINT8	eg_sel_dr;	/* (decay state)                */
  89.183 +	UINT32	eg_m_rr;	/* (release state)              */
  89.184 +	UINT8	eg_sh_rr;	/* (release state)              */
  89.185 +	UINT8	eg_sel_rr;	/* (release state)              */
  89.186 +
  89.187 +	UINT32	key;		/* 0 = KEY OFF, >0 = KEY ON     */
  89.188 +
  89.189 +	/* LFO */
  89.190 +	UINT32	AMmask;		/* LFO Amplitude Modulation enable mask */
  89.191 +	UINT8	vib;		/* LFO Phase Modulation enable flag (active high)*/
  89.192 +
  89.193 +	/* waveform select */
  89.194 +	UINT8	waveform_number;
  89.195 +	unsigned int wavetable;
  89.196 +
  89.197 +//unsigned char reserved[128-84];//speedup: pump up the struct size to power of 2
  89.198 +unsigned char reserved[128-100];//speedup: pump up the struct size to power of 2
  89.199 +
  89.200 +} OPL3_SLOT;
  89.201 +
  89.202 +typedef struct{
  89.203 +	OPL3_SLOT SLOT[2];
  89.204 +
  89.205 +	UINT32	block_fnum;	/* block+fnum                   */
  89.206 +	UINT32	fc;			/* Freq. Increment base         */
  89.207 +	UINT32	ksl_base;	/* KeyScaleLevel Base step      */
  89.208 +	UINT8	kcode;		/* key code (for key scaling)   */
  89.209 +
  89.210 +	/*
  89.211 +       there are 12 2-operator channels which can be combined in pairs
  89.212 +       to form six 4-operator channel, they are:
  89.213 +        0 and 3,
  89.214 +        1 and 4,
  89.215 +        2 and 5,
  89.216 +        9 and 12,
  89.217 +        10 and 13,
  89.218 +        11 and 14
  89.219 +    */
  89.220 +	UINT8	extended;	/* set to 1 if this channel forms up a 4op channel with another channel(only used by first of pair of channels, ie 0,1,2 and 9,10,11) */
  89.221 +
  89.222 +unsigned char reserved[512-272];//speedup:pump up the struct size to power of 2
  89.223 +
  89.224 +} OPL3_CH;
  89.225 +
  89.226 +/* OPL3 state */
  89.227 +typedef struct {
  89.228 +	OPL3_CH	P_CH[18];				/* OPL3 chips have 18 channels  */
  89.229 +
  89.230 +	UINT32	pan[18*4];				/* channels output masks (0xffffffff = enable); 4 masks per one channel */
  89.231 +	UINT32	pan_ctrl_value[18];		/* output control values 1 per one channel (1 value contains 4 masks) */
  89.232 +
  89.233 +	UINT32	eg_cnt;					/* global envelope generator counter    */
  89.234 +	UINT32	eg_timer;				/* global envelope generator counter works at frequency = chipclock/288 (288=8*36) */
  89.235 +	UINT32	eg_timer_add;			/* step of eg_timer                     */
  89.236 +	UINT32	eg_timer_overflow;		/* envelope generator timer overlfows every 1 sample (on real chip) */
  89.237 +
  89.238 +	UINT32	fn_tab[1024];			/* fnumber->increment counter   */
  89.239 +
  89.240 +	/* LFO */
  89.241 +	UINT8	lfo_am_depth;
  89.242 +	UINT8	lfo_pm_depth_range;
  89.243 +	UINT32	lfo_am_cnt;
  89.244 +	UINT32	lfo_am_inc;
  89.245 +	UINT32	lfo_pm_cnt;
  89.246 +	UINT32	lfo_pm_inc;
  89.247 +
  89.248 +	UINT32	noise_rng;				/* 23 bit noise shift register  */
  89.249 +	UINT32	noise_p;				/* current noise 'phase'        */
  89.250 +	UINT32	noise_f;				/* current noise period         */
  89.251 +
  89.252 +	UINT8	OPL3_mode;				/* OPL3 extension enable flag   */
  89.253 +
  89.254 +	UINT8	rhythm;					/* Rhythm mode                  */
  89.255 +
  89.256 +	int		T[2];					/* timer counters               */
  89.257 +	UINT8	st[2];					/* timer enable                 */
  89.258 +
  89.259 +	UINT32	address;				/* address register             */
  89.260 +	UINT8	status;					/* status flag                  */
  89.261 +	UINT8	statusmask;				/* status mask                  */
  89.262 +
  89.263 +	UINT8	nts;					/* NTS (note select)            */
  89.264 +
  89.265 +	/* external event callback handlers */
  89.266 +	OPL3_TIMERHANDLER  timer_handler;/* TIMER handler                */
  89.267 +	void *TimerParam;					/* TIMER parameter              */
  89.268 +	OPL3_IRQHANDLER    IRQHandler;	/* IRQ handler                  */
  89.269 +	void *IRQParam;					/* IRQ parameter                */
  89.270 +	OPL3_UPDATEHANDLER UpdateHandler;/* stream update handler       */
  89.271 +	void *UpdateParam;				/* stream update parameter      */
  89.272 +
  89.273 +	UINT8 type;						/* chip type                    */
  89.274 +	int clock;						/* master clock  (Hz)           */
  89.275 +	int rate;						/* sampling rate (Hz)           */
  89.276 +	double freqbase;				/* frequency base               */
  89.277 +	attotime TimerBase;			/* Timer base time (==sampling time)*/
  89.278 +	running_device *device;
  89.279 +} OPL3;
  89.280 +
  89.281 +
  89.282 +
  89.283 +/* mapping of register number (offset) to slot number used by the emulator */
  89.284 +static const int slot_array[32]=
  89.285 +{
  89.286 +	 0, 2, 4, 1, 3, 5,-1,-1,
  89.287 +	 6, 8,10, 7, 9,11,-1,-1,
  89.288 +	12,14,16,13,15,17,-1,-1,
  89.289 +	-1,-1,-1,-1,-1,-1,-1,-1
  89.290 +};
  89.291 +
  89.292 +/* key scale level */
  89.293 +/* table is 3dB/octave , DV converts this into 6dB/octave */
  89.294 +/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
  89.295 +#define DV (0.1875/2.0)
  89.296 +static const UINT32 ksl_tab[8*16]=
  89.297 +{
  89.298 +	/* OCT 0 */
  89.299 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.300 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.301 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.302 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.303 +	/* OCT 1 */
  89.304 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.305 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.306 +	 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
  89.307 +	 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
  89.308 +	/* OCT 2 */
  89.309 +	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
  89.310 +	 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
  89.311 +	 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
  89.312 +	 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
  89.313 +	/* OCT 3 */
  89.314 +	 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
  89.315 +	 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
  89.316 +	 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
  89.317 +	 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
  89.318 +	/* OCT 4 */
  89.319 +	 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
  89.320 +	 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
  89.321 +	 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
  89.322 +	10.875/DV,11.250/DV,11.625/DV,12.000/DV,
  89.323 +	/* OCT 5 */
  89.324 +	 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
  89.325 +	 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
  89.326 +	12.000/DV,12.750/DV,13.125/DV,13.500/DV,
  89.327 +	13.875/DV,14.250/DV,14.625/DV,15.000/DV,
  89.328 +	/* OCT 6 */
  89.329 +	 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
  89.330 +	12.000/DV,13.125/DV,13.875/DV,14.625/DV,
  89.331 +	15.000/DV,15.750/DV,16.125/DV,16.500/DV,
  89.332 +	16.875/DV,17.250/DV,17.625/DV,18.000/DV,
  89.333 +	/* OCT 7 */
  89.334 +	 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
  89.335 +	15.000/DV,16.125/DV,16.875/DV,17.625/DV,
  89.336 +	18.000/DV,18.750/DV,19.125/DV,19.500/DV,
  89.337 +	19.875/DV,20.250/DV,20.625/DV,21.000/DV
  89.338 +};
  89.339 +#undef DV
  89.340 +
  89.341 +/* sustain level table (3dB per step) */
  89.342 +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
  89.343 +#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
  89.344 +static const UINT32 sl_tab[16]={
  89.345 + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
  89.346 + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
  89.347 +};
  89.348 +#undef SC
  89.349 +
  89.350 +
  89.351 +#define RATE_STEPS (8)
  89.352 +static const unsigned char eg_inc[15*RATE_STEPS]={
  89.353 +
  89.354 +/*cycle:0 1  2 3  4 5  6 7*/
  89.355 +
  89.356 +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
  89.357 +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
  89.358 +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
  89.359 +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
  89.360 +
  89.361 +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
  89.362 +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
  89.363 +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
  89.364 +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
  89.365 +
  89.366 +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
  89.367 +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
  89.368 +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
  89.369 +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
  89.370 +
  89.371 +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 for decay */
  89.372 +/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 for attack (zero time) */
  89.373 +/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
  89.374 +};
  89.375 +
  89.376 +
  89.377 +#define O(a) (a*RATE_STEPS)
  89.378 +
  89.379 +/* note that there is no O(13) in this table - it's directly in the code */
  89.380 +static const unsigned char eg_rate_select[16+64+16]={	/* Envelope Generator rates (16 + 64 rates + 16 RKS) */
  89.381 +/* 16 infinite time rates */
  89.382 +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
  89.383 +O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
  89.384 +
  89.385 +/* rates 00-12 */
  89.386 +O( 0),O( 1),O( 2),O( 3),
  89.387 +O( 0),O( 1),O( 2),O( 3),
  89.388 +O( 0),O( 1),O( 2),O( 3),
  89.389 +O( 0),O( 1),O( 2),O( 3),
  89.390 +O( 0),O( 1),O( 2),O( 3),
  89.391 +O( 0),O( 1),O( 2),O( 3),
  89.392 +O( 0),O( 1),O( 2),O( 3),
  89.393 +O( 0),O( 1),O( 2),O( 3),
  89.394 +O( 0),O( 1),O( 2),O( 3),
  89.395 +O( 0),O( 1),O( 2),O( 3),
  89.396 +O( 0),O( 1),O( 2),O( 3),
  89.397 +O( 0),O( 1),O( 2),O( 3),
  89.398 +O( 0),O( 1),O( 2),O( 3),
  89.399 +
  89.400 +/* rate 13 */
  89.401 +O( 4),O( 5),O( 6),O( 7),
  89.402 +
  89.403 +/* rate 14 */
  89.404 +O( 8),O( 9),O(10),O(11),
  89.405 +
  89.406 +/* rate 15 */
  89.407 +O(12),O(12),O(12),O(12),
  89.408 +
  89.409 +/* 16 dummy rates (same as 15 3) */
  89.410 +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
  89.411 +O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
  89.412 +
  89.413 +};
  89.414 +#undef O
  89.415 +
  89.416 +/*rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15 */
  89.417 +/*shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0  */
  89.418 +/*mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0  */
  89.419 +
  89.420 +#define O(a) (a*1)
  89.421 +static const unsigned char eg_rate_shift[16+64+16]={	/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
  89.422 +/* 16 infinite time rates */
  89.423 +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
  89.424 +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
  89.425 +
  89.426 +/* rates 00-12 */
  89.427 +O(12),O(12),O(12),O(12),
  89.428 +O(11),O(11),O(11),O(11),
  89.429 +O(10),O(10),O(10),O(10),
  89.430 +O( 9),O( 9),O( 9),O( 9),
  89.431 +O( 8),O( 8),O( 8),O( 8),
  89.432 +O( 7),O( 7),O( 7),O( 7),
  89.433 +O( 6),O( 6),O( 6),O( 6),
  89.434 +O( 5),O( 5),O( 5),O( 5),
  89.435 +O( 4),O( 4),O( 4),O( 4),
  89.436 +O( 3),O( 3),O( 3),O( 3),
  89.437 +O( 2),O( 2),O( 2),O( 2),
  89.438 +O( 1),O( 1),O( 1),O( 1),
  89.439 +O( 0),O( 0),O( 0),O( 0),
  89.440 +
  89.441 +/* rate 13 */
  89.442 +O( 0),O( 0),O( 0),O( 0),
  89.443 +
  89.444 +/* rate 14 */
  89.445 +O( 0),O( 0),O( 0),O( 0),
  89.446 +
  89.447 +/* rate 15 */
  89.448 +O( 0),O( 0),O( 0),O( 0),
  89.449 +
  89.450 +/* 16 dummy rates (same as 15 3) */
  89.451 +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
  89.452 +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
  89.453 +
  89.454 +};
  89.455 +#undef O
  89.456 +
  89.457 +
  89.458 +/* multiple table */
  89.459 +#define ML 2
  89.460 +static const UINT8 mul_tab[16]= {
  89.461 +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
  89.462 +   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
  89.463 +   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
  89.464 +};
  89.465 +#undef ML
  89.466 +
  89.467 +/*  TL_TAB_LEN is calculated as:
  89.468 +
  89.469 +*   (12+1)=13 - sinus amplitude bits     (Y axis)
  89.470 +*   additional 1: to compensate for calculations of negative part of waveform
  89.471 +*   (if we don't add it then the greatest possible _negative_ value would be -2
  89.472 +*   and we really need -1 for waveform #7)
  89.473 +*   2  - sinus sign bit           (Y axis)
  89.474 +*   TL_RES_LEN - sinus resolution (X axis)
  89.475 +*/
  89.476 +#define TL_TAB_LEN (13*2*TL_RES_LEN)
  89.477 +static signed int tl_tab[TL_TAB_LEN];
  89.478 +
  89.479 +#define ENV_QUIET		(TL_TAB_LEN>>4)
  89.480 +
  89.481 +/* sin waveform table in 'decibel' scale */
  89.482 +/* there are eight waveforms on OPL3 chips */
  89.483 +static unsigned int sin_tab[SIN_LEN * 8];
  89.484 +
  89.485 +
  89.486 +/* LFO Amplitude Modulation table (verified on real YM3812)
  89.487 +   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
  89.488 +
  89.489 +   Length: 210 elements.
  89.490 +
  89.491 +    Each of the elements has to be repeated
  89.492 +    exactly 64 times (on 64 consecutive samples).
  89.493 +    The whole table takes: 64 * 210 = 13440 samples.
  89.494 +
  89.495 +    When AM = 1 data is used directly
  89.496 +    When AM = 0 data is divided by 4 before being used (loosing precision is important)
  89.497 +*/
  89.498 +
  89.499 +#define LFO_AM_TAB_ELEMENTS 210
  89.500 +
  89.501 +static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
  89.502 +0,0,0,0,0,0,0,
  89.503 +1,1,1,1,
  89.504 +2,2,2,2,
  89.505 +3,3,3,3,
  89.506 +4,4,4,4,
  89.507 +5,5,5,5,
  89.508 +6,6,6,6,
  89.509 +7,7,7,7,
  89.510 +8,8,8,8,
  89.511 +9,9,9,9,
  89.512 +10,10,10,10,
  89.513 +11,11,11,11,
  89.514 +12,12,12,12,
  89.515 +13,13,13,13,
  89.516 +14,14,14,14,
  89.517 +15,15,15,15,
  89.518 +16,16,16,16,
  89.519 +17,17,17,17,
  89.520 +18,18,18,18,
  89.521 +19,19,19,19,
  89.522 +20,20,20,20,
  89.523 +21,21,21,21,
  89.524 +22,22,22,22,
  89.525 +23,23,23,23,
  89.526 +24,24,24,24,
  89.527 +25,25,25,25,
  89.528 +26,26,26,
  89.529 +25,25,25,25,
  89.530 +24,24,24,24,
  89.531 +23,23,23,23,
  89.532 +22,22,22,22,
  89.533 +21,21,21,21,
  89.534 +20,20,20,20,
  89.535 +19,19,19,19,
  89.536 +18,18,18,18,
  89.537 +17,17,17,17,
  89.538 +16,16,16,16,
  89.539 +15,15,15,15,
  89.540 +14,14,14,14,
  89.541 +13,13,13,13,
  89.542 +12,12,12,12,
  89.543 +11,11,11,11,
  89.544 +10,10,10,10,
  89.545 +9,9,9,9,
  89.546 +8,8,8,8,
  89.547 +7,7,7,7,
  89.548 +6,6,6,6,
  89.549 +5,5,5,5,
  89.550 +4,4,4,4,
  89.551 +3,3,3,3,
  89.552 +2,2,2,2,
  89.553 +1,1,1,1
  89.554 +};
  89.555 +
  89.556 +/* LFO Phase Modulation table (verified on real YM3812) */
  89.557 +static const INT8 lfo_pm_table[8*8*2] = {
  89.558 +
  89.559 +/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
  89.560 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
  89.561 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 1*/
  89.562 +
  89.563 +/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */
  89.564 +0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
  89.565 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 1*/
  89.566 +
  89.567 +/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */
  89.568 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
  89.569 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 1*/
  89.570 +
  89.571 +/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */
  89.572 +1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
  89.573 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 1*/
  89.574 +
  89.575 +/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */
  89.576 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
  89.577 +4, 2, 0,-2,-4,-2, 0, 2,	/*LFO PM depth = 1*/
  89.578 +
  89.579 +/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */
  89.580 +2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
  89.581 +5, 2, 0,-2,-5,-2, 0, 2,	/*LFO PM depth = 1*/
  89.582 +
  89.583 +/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */
  89.584 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
  89.585 +6, 3, 0,-3,-6,-3, 0, 3,	/*LFO PM depth = 1*/
  89.586 +
  89.587 +/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */
  89.588 +3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
  89.589 +7, 3, 0,-3,-7,-3, 0, 3	/*LFO PM depth = 1*/
  89.590 +};
  89.591 +
  89.592 +
  89.593 +/* lock level of common table */
  89.594 +static int num_lock = 0;
  89.595 +
  89.596 +/* work table */
  89.597 +static void *cur_chip = NULL;			/* current chip point */
  89.598 +static OPL3_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
  89.599 +
  89.600 +static signed int phase_modulation;		/* phase modulation input (SLOT 2) */
  89.601 +static signed int phase_modulation2;	/* phase modulation input (SLOT 3 in 4 operator channels) */
  89.602 +static signed int chanout[18];			/* 18 channels */
  89.603 +
  89.604 +
  89.605 +static UINT32	LFO_AM;
  89.606 +static INT32	LFO_PM;
  89.607 +
  89.608 +
  89.609 +
  89.610 +INLINE int limit( int val, int max, int min ) {
  89.611 +	if ( val > max )
  89.612 +		val = max;
  89.613 +	else if ( val < min )
  89.614 +		val = min;
  89.615 +
  89.616 +	return val;
  89.617 +}
  89.618 +
  89.619 +
  89.620 +/* status set and IRQ handling */
  89.621 +INLINE void OPL3_STATUS_SET(OPL3 *chip,int flag)
  89.622 +{
  89.623 +	/* set status flag masking out disabled IRQs */
  89.624 +	chip->status |= (flag & chip->statusmask);
  89.625 +	if(!(chip->status & 0x80))
  89.626 +	{
  89.627 +		if(chip->status & 0x7f)
  89.628 +		{	/* IRQ on */
  89.629 +			chip->status |= 0x80;
  89.630 +			/* callback user interrupt handler (IRQ is OFF to ON) */
  89.631 +			if(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,1);
  89.632 +		}
  89.633 +	}
  89.634 +	pclog("Set %i %02X\n",flag,chip->status);
  89.635 +}
  89.636 +
  89.637 +/* status reset and IRQ handling */
  89.638 +INLINE void OPL3_STATUS_RESET(OPL3 *chip,int flag)
  89.639 +{
  89.640 +	/* reset status flag */
  89.641 +	chip->status &= ~flag;
  89.642 +	if(chip->status & 0x80)
  89.643 +	{
  89.644 +		if (!(chip->status & 0x7f))
  89.645 +		{
  89.646 +			chip->status &= 0x7f;
  89.647 +			/* callback user interrupt handler (IRQ is ON to OFF) */
  89.648 +			if(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,0);
  89.649 +		}
  89.650 +	}
  89.651 +	pclog("Reset %i %02X\n",flag,chip->status);
  89.652 +}
  89.653 +
  89.654 +/* IRQ mask set */
  89.655 +INLINE void OPL3_STATUSMASK_SET(OPL3 *chip,int flag)
  89.656 +{
  89.657 +	chip->statusmask = flag;
  89.658 +	/* IRQ handling check */
  89.659 +	OPL3_STATUS_SET(chip,0);
  89.660 +	OPL3_STATUS_RESET(chip,0);
  89.661 +}
  89.662 +
  89.663 +
  89.664 +/* advance LFO to next sample */
  89.665 +INLINE void advance_lfo(OPL3 *chip)
  89.666 +{
  89.667 +	UINT8 tmp;
  89.668 +
  89.669 +	/* LFO */
  89.670 +	chip->lfo_am_cnt += chip->lfo_am_inc;
  89.671 +	if (chip->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )	/* lfo_am_table is 210 elements long */
  89.672 +		chip->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);
  89.673 +
  89.674 +	tmp = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ];
  89.675 +
  89.676 +	if (chip->lfo_am_depth)
  89.677 +		LFO_AM = tmp;
  89.678 +	else
  89.679 +		LFO_AM = tmp>>2;
  89.680 +
  89.681 +	chip->lfo_pm_cnt += chip->lfo_pm_inc;
  89.682 +	LFO_PM = ((chip->lfo_pm_cnt>>LFO_SH) & 7) | chip->lfo_pm_depth_range;
  89.683 +}
  89.684 +
  89.685 +/* advance to next sample */
  89.686 +INLINE void advance(OPL3 *chip)
  89.687 +{
  89.688 +	OPL3_CH *CH;
  89.689 +	OPL3_SLOT *op;
  89.690 +	int i;
  89.691 +
  89.692 +	chip->eg_timer += chip->eg_timer_add;
  89.693 +
  89.694 +	while (chip->eg_timer >= chip->eg_timer_overflow)
  89.695 +	{
  89.696 +		chip->eg_timer -= chip->eg_timer_overflow;
  89.697 +
  89.698 +		chip->eg_cnt++;
  89.699 +
  89.700 +		for (i=0; i<9*2*2; i++)
  89.701 +		{
  89.702 +			CH  = &chip->P_CH[i/2];
  89.703 +			op  = &CH->SLOT[i&1];
  89.704 +#if 1
  89.705 +			/* Envelope Generator */
  89.706 +			switch(op->state)
  89.707 +			{
  89.708 +			case EG_ATT:	/* attack phase */
  89.709 +//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
  89.710 +				if ( !(chip->eg_cnt & op->eg_m_ar) )
  89.711 +				{
  89.712 +					op->volume += (~op->volume *
  89.713 +	                        		           (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)])
  89.714 +        			                          ) >>3;
  89.715 +
  89.716 +					if (op->volume <= MIN_ATT_INDEX)
  89.717 +					{
  89.718 +						op->volume = MIN_ATT_INDEX;
  89.719 +						op->state = EG_DEC;
  89.720 +					}
  89.721 +
  89.722 +				}
  89.723 +			break;
  89.724 +
  89.725 +			case EG_DEC:	/* decay phase */
  89.726 +//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
  89.727 +				if ( !(chip->eg_cnt & op->eg_m_dr) )
  89.728 +				{
  89.729 +					op->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)];
  89.730 +
  89.731 +					if ( op->volume >= op->sl )
  89.732 +						op->state = EG_SUS;
  89.733 +
  89.734 +				}
  89.735 +			break;
  89.736 +
  89.737 +			case EG_SUS:	/* sustain phase */
  89.738 +
  89.739 +				/* this is important behaviour:
  89.740 +                one can change percusive/non-percussive modes on the fly and
  89.741 +                the chip will remain in sustain phase - verified on real YM3812 */
  89.742 +
  89.743 +				if(op->eg_type)		/* non-percussive mode */
  89.744 +				{
  89.745 +									/* do nothing */
  89.746 +				}
  89.747 +				else				/* percussive mode */
  89.748 +				{
  89.749 +					/* during sustain phase chip adds Release Rate (in percussive mode) */
  89.750 +//                  if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
  89.751 +					if ( !(chip->eg_cnt & op->eg_m_rr) )
  89.752 +					{
  89.753 +						op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];
  89.754 +
  89.755 +						if ( op->volume >= MAX_ATT_INDEX )
  89.756 +							op->volume = MAX_ATT_INDEX;
  89.757 +					}
  89.758 +					/* else do nothing in sustain phase */
  89.759 +				}
  89.760 +			break;
  89.761 +
  89.762 +			case EG_REL:	/* release phase */
  89.763 +//              if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
  89.764 +				if ( !(chip->eg_cnt & op->eg_m_rr) )
  89.765 +				{
  89.766 +					op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];
  89.767 +
  89.768 +					if ( op->volume >= MAX_ATT_INDEX )
  89.769 +					{
  89.770 +						op->volume = MAX_ATT_INDEX;
  89.771 +						op->state = EG_OFF;
  89.772 +					}
  89.773 +
  89.774 +				}
  89.775 +			break;
  89.776 +
  89.777 +			default:
  89.778 +			break;
  89.779 +			}
  89.780 +#endif
  89.781 +		}
  89.782 +	}
  89.783 +
  89.784 +	for (i=0; i<9*2*2; i++)
  89.785 +	{
  89.786 +		CH  = &chip->P_CH[i/2];
  89.787 +		op  = &CH->SLOT[i&1];
  89.788 +
  89.789 +		/* Phase Generator */
  89.790 +		if(op->vib)
  89.791 +		{
  89.792 +			UINT8 block;
  89.793 +			unsigned int block_fnum = CH->block_fnum;
  89.794 +
  89.795 +			unsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;
  89.796 +
  89.797 +			signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
  89.798 +
  89.799 +			if (lfo_fn_table_index_offset)	/* LFO phase modulation active */
  89.800 +			{
  89.801 +				block_fnum += lfo_fn_table_index_offset;
  89.802 +				block = (block_fnum&0x1c00) >> 10;
  89.803 +				op->Cnt += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
  89.804 +			}
  89.805 +			else	/* LFO phase modulation  = zero */
  89.806 +			{
  89.807 +				op->Cnt += op->Incr;
  89.808 +			}
  89.809 +		}
  89.810 +		else	/* LFO phase modulation disabled for this operator */
  89.811 +		{
  89.812 +			op->Cnt += op->Incr;
  89.813 +		}
  89.814 +	}
  89.815 +
  89.816 +	/*  The Noise Generator of the YM3812 is 23-bit shift register.
  89.817 +    *   Period is equal to 2^23-2 samples.
  89.818 +    *   Register works at sampling frequency of the chip, so output
  89.819 +    *   can change on every sample.
  89.820 +    *
  89.821 +    *   Output of the register and input to the bit 22 is:
  89.822 +    *   bit0 XOR bit14 XOR bit15 XOR bit22
  89.823 +    *
  89.824 +    *   Simply use bit 22 as the noise output.
  89.825 +    */
  89.826 +
  89.827 +	chip->noise_p += chip->noise_f;
  89.828 +	i = chip->noise_p >> FREQ_SH;		/* number of events (shifts of the shift register) */
  89.829 +	chip->noise_p &= FREQ_MASK;
  89.830 +	while (i)
  89.831 +	{
  89.832 +		/*
  89.833 +        UINT32 j;
  89.834 +        j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1;
  89.835 +        chip->noise_rng = (j<<22) | (chip->noise_rng>>1);
  89.836 +        */
  89.837 +
  89.838 +		/*
  89.839 +            Instead of doing all the logic operations above, we
  89.840 +            use a trick here (and use bit 0 as the noise output).
  89.841 +            The difference is only that the noise bit changes one
  89.842 +            step ahead. This doesn't matter since we don't know
  89.843 +            what is real state of the noise_rng after the reset.
  89.844 +        */
  89.845 +
  89.846 +		if (chip->noise_rng & 1) chip->noise_rng ^= 0x800302;
  89.847 +		chip->noise_rng >>= 1;
  89.848 +
  89.849 +		i--;
  89.850 +	}
  89.851 +}
  89.852 +
  89.853 +
  89.854 +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
  89.855 +{
  89.856 +	UINT32 p;
  89.857 +
  89.858 +	p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
  89.859 +
  89.860 +	if (p >= TL_TAB_LEN)
  89.861 +		return 0;
  89.862 +	return tl_tab[p];
  89.863 +}
  89.864 +
  89.865 +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
  89.866 +{
  89.867 +	UINT32 p;
  89.868 +
  89.869 +	p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm))>>FREQ_SH) & SIN_MASK)];
  89.870 +
  89.871 +	if (p >= TL_TAB_LEN)
  89.872 +		return 0;
  89.873 +	return tl_tab[p];
  89.874 +}
  89.875 +
  89.876 +
  89.877 +#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
  89.878 +
  89.879 +/* calculate output of a standard 2 operator channel
  89.880 + (or 1st part of a 4-op channel) */
  89.881 +INLINE void chan_calc( OPL3_CH *CH )
  89.882 +{
  89.883 +	OPL3_SLOT *SLOT;
  89.884 +	unsigned int env;
  89.885 +	signed int out;
  89.886 +
  89.887 +	phase_modulation = 0;
  89.888 +	phase_modulation2= 0;
  89.889 +
  89.890 +	/* SLOT 1 */
  89.891 +	SLOT = &CH->SLOT[SLOT1];
  89.892 +	env  = volume_calc(SLOT);
  89.893 +	out  = SLOT->op1_out[0] + SLOT->op1_out[1];
  89.894 +	SLOT->op1_out[0] = SLOT->op1_out[1];
  89.895 +	SLOT->op1_out[1] = 0;
  89.896 +	if( env < ENV_QUIET )
  89.897 +	{
  89.898 +		if (!SLOT->FB)
  89.899 +			out = 0;
  89.900 +		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
  89.901 +	}
  89.902 +	*SLOT->connect += SLOT->op1_out[1];
  89.903 +//logerror("out0=%5i vol0=%4i ", SLOT->op1_out[1], env );
  89.904 +
  89.905 +	/* SLOT 2 */
  89.906 +	SLOT++;
  89.907 +	env = volume_calc(SLOT);
  89.908 +	if( env < ENV_QUIET )
  89.909 +		*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
  89.910 +
  89.911 +//logerror("out1=%5i vol1=%4i\n", op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable), env );
  89.912 +
  89.913 +}
  89.914 +
  89.915 +/* calculate output of a 2nd part of 4-op channel */
  89.916 +INLINE void chan_calc_ext( OPL3_CH *CH )
  89.917 +{
  89.918 +	OPL3_SLOT *SLOT;
  89.919 +	unsigned int env;
  89.920 +
  89.921 +	phase_modulation = 0;
  89.922 +
  89.923 +	/* SLOT 1 */
  89.924 +	SLOT = &CH->SLOT[SLOT1];
  89.925 +	env  = volume_calc(SLOT);
  89.926 +	if( env < ENV_QUIET )
  89.927 +		*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation2, SLOT->wavetable );
  89.928 +
  89.929 +	/* SLOT 2 */
  89.930 +	SLOT++;
  89.931 +	env = volume_calc(SLOT);
  89.932 +	if( env < ENV_QUIET )
  89.933 +		*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
  89.934 +
  89.935 +}
  89.936 +
  89.937 +/*
  89.938 +    operators used in the rhythm sounds generation process:
  89.939 +
  89.940 +    Envelope Generator:
  89.941 +
  89.942 +channel  operator  register number   Bass  High  Snare Tom  Top
  89.943 +/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal
  89.944 + 6 / 0   12        50  70   90   f0  +
  89.945 + 6 / 1   15        53  73   93   f3  +
  89.946 + 7 / 0   13        51  71   91   f1        +
  89.947 + 7 / 1   16        54  74   94   f4              +
  89.948 + 8 / 0   14        52  72   92   f2                    +
  89.949 + 8 / 1   17        55  75   95   f5                          +
  89.950 +
  89.951 +    Phase Generator:
  89.952 +
  89.953 +channel  operator  register number   Bass  High  Snare Tom  Top
  89.954 +/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal
  89.955 + 6 / 0   12        30                +
  89.956 + 6 / 1   15        33                +
  89.957 + 7 / 0   13        31                      +     +           +
  89.958 + 7 / 1   16        34                -----  n o t  u s e d -----
  89.959 + 8 / 0   14        32                                  +
  89.960 + 8 / 1   17        35                      +                 +
  89.961 +
  89.962 +channel  operator  register number   Bass  High  Snare Tom  Top
  89.963 +number   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal
  89.964 +   6     12,15     B6        A6      +
  89.965 +
  89.966 +   7     13,16     B7        A7            +     +           +
  89.967 +
  89.968 +   8     14,17     B8        A8            +           +     +
  89.969 +
  89.970 +*/
  89.971 +
  89.972 +/* calculate rhythm */
  89.973 +
  89.974 +INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise )
  89.975 +{
  89.976 +	OPL3_SLOT *SLOT;
  89.977 +	signed int out;
  89.978 +	unsigned int env;
  89.979 +
  89.980 +
  89.981 +	/* Bass Drum (verified on real YM3812):
  89.982 +      - depends on the channel 6 'connect' register:
  89.983 +          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
  89.984 +          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
  89.985 +      - output sample always is multiplied by 2
  89.986 +    */
  89.987 +
  89.988 +	phase_modulation = 0;
  89.989 +
  89.990 +	/* SLOT 1 */
  89.991 +	SLOT = &CH[6].SLOT[SLOT1];
  89.992 +	env = volume_calc(SLOT);
  89.993 +
  89.994 +	out = SLOT->op1_out[0] + SLOT->op1_out[1];
  89.995 +	SLOT->op1_out[0] = SLOT->op1_out[1];
  89.996 +
  89.997 +	if (!SLOT->CON)
  89.998 +		phase_modulation = SLOT->op1_out[0];
  89.999 +	//else ignore output of operator 1
 89.1000 +
 89.1001 +	SLOT->op1_out[1] = 0;
 89.1002 +	if( env < ENV_QUIET )
 89.1003 +	{
 89.1004 +		if (!SLOT->FB)
 89.1005 +			out = 0;
 89.1006 +		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
 89.1007 +	}
 89.1008 +
 89.1009 +	/* SLOT 2 */
 89.1010 +	SLOT++;
 89.1011 +	env = volume_calc(SLOT);
 89.1012 +	if( env < ENV_QUIET )
 89.1013 +		chanout[6] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
 89.1014 +
 89.1015 +
 89.1016 +	/* Phase generation is based on: */
 89.1017 +	// HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases)
 89.1018 +	// SD  (16) channel 7->slot 1
 89.1019 +	// TOM (14) channel 8->slot 1
 89.1020 +	// TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases)
 89.1021 +
 89.1022 +	/* Envelope generation based on: */
 89.1023 +	// HH  channel 7->slot1
 89.1024 +	// SD  channel 7->slot2
 89.1025 +	// TOM channel 8->slot1
 89.1026 +	// TOP channel 8->slot2
 89.1027 +
 89.1028 +
 89.1029 +	/* The following formulas can be well optimized.
 89.1030 +       I leave them in direct form for now (in case I've missed something).
 89.1031 +    */
 89.1032 +
 89.1033 +	/* High Hat (verified on real YM3812) */
 89.1034 +	env = volume_calc(SLOT7_1);
 89.1035 +	if( env < ENV_QUIET )
 89.1036 +	{
 89.1037 +
 89.1038 +		/* high hat phase generation:
 89.1039 +            phase = d0 or 234 (based on frequency only)
 89.1040 +            phase = 34 or 2d0 (based on noise)
 89.1041 +        */
 89.1042 +
 89.1043 +		/* base frequency derived from operator 1 in channel 7 */
 89.1044 +		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
 89.1045 +		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
 89.1046 +		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
 89.1047 +
 89.1048 +		unsigned char res1 = (bit2 ^ bit7) | bit3;
 89.1049 +
 89.1050 +		/* when res1 = 0 phase = 0x000 | 0xd0; */
 89.1051 +		/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
 89.1052 +		UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
 89.1053 +
 89.1054 +		/* enable gate based on frequency of operator 2 in channel 8 */
 89.1055 +		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
 89.1056 +		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
 89.1057 +
 89.1058 +		unsigned char res2 = (bit3e ^ bit5e);
 89.1059 +
 89.1060 +		/* when res2 = 0 pass the phase from calculation above (res1); */
 89.1061 +		/* when res2 = 1 phase = 0x200 | (0xd0>>2); */
 89.1062 +		if (res2)
 89.1063 +			phase = (0x200|(0xd0>>2));
 89.1064 +
 89.1065 +
 89.1066 +		/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
 89.1067 +		/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
 89.1068 +		if (phase&0x200)
 89.1069 +		{
 89.1070 +			if (noise)
 89.1071 +				phase = 0x200|0xd0;
 89.1072 +		}
 89.1073 +		else
 89.1074 +		/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
 89.1075 +		/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
 89.1076 +		{
 89.1077 +			if (noise)
 89.1078 +				phase = 0xd0>>2;
 89.1079 +		}
 89.1080 +
 89.1081 +		chanout[7] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
 89.1082 +	}
 89.1083 +
 89.1084 +	/* Snare Drum (verified on real YM3812) */
 89.1085 +	env = volume_calc(SLOT7_2);
 89.1086 +	if( env < ENV_QUIET )
 89.1087 +	{
 89.1088 +		/* base frequency derived from operator 1 in channel 7 */
 89.1089 +		unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
 89.1090 +
 89.1091 +		/* when bit8 = 0 phase = 0x100; */
 89.1092 +		/* when bit8 = 1 phase = 0x200; */
 89.1093 +		UINT32 phase = bit8 ? 0x200 : 0x100;
 89.1094 +
 89.1095 +		/* Noise bit XOR'es phase by 0x100 */
 89.1096 +		/* when noisebit = 0 pass the phase from calculation above */
 89.1097 +		/* when noisebit = 1 phase ^= 0x100; */
 89.1098 +		/* in other words: phase ^= (noisebit<<8); */
 89.1099 +		if (noise)
 89.1100 +			phase ^= 0x100;
 89.1101 +
 89.1102 +		chanout[7] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
 89.1103 +	}
 89.1104 +
 89.1105 +	/* Tom Tom (verified on real YM3812) */
 89.1106 +	env = volume_calc(SLOT8_1);
 89.1107 +	if( env < ENV_QUIET )
 89.1108 +		chanout[8] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;
 89.1109 +
 89.1110 +	/* Top Cymbal (verified on real YM3812) */
 89.1111 +	env = volume_calc(SLOT8_2);
 89.1112 +	if( env < ENV_QUIET )
 89.1113 +	{
 89.1114 +		/* base frequency derived from operator 1 in channel 7 */
 89.1115 +		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
 89.1116 +		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
 89.1117 +		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
 89.1118 +
 89.1119 +		unsigned char res1 = (bit2 ^ bit7) | bit3;
 89.1120 +
 89.1121 +		/* when res1 = 0 phase = 0x000 | 0x100; */
 89.1122 +		/* when res1 = 1 phase = 0x200 | 0x100; */
 89.1123 +		UINT32 phase = res1 ? 0x300 : 0x100;
 89.1124 +
 89.1125 +		/* enable gate based on frequency of operator 2 in channel 8 */
 89.1126 +		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
 89.1127 +		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
 89.1128 +
 89.1129 +		unsigned char res2 = (bit3e ^ bit5e);
 89.1130 +		/* when res2 = 0 pass the phase from calculation above (res1); */
 89.1131 +		/* when res2 = 1 phase = 0x200 | 0x100; */
 89.1132 +		if (res2)
 89.1133 +			phase = 0x300;
 89.1134 +
 89.1135 +		chanout[8] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
 89.1136 +	}
 89.1137 +
 89.1138 +}
 89.1139 +
 89.1140 +
 89.1141 +/* generic table initialize */
 89.1142 +static int init_tables(void)
 89.1143 +{
 89.1144 +	signed int i,x;
 89.1145 +	signed int n;
 89.1146 +	double o,m;
 89.1147 +
 89.1148 +
 89.1149 +	for (x=0; x<TL_RES_LEN; x++)
 89.1150 +	{
 89.1151 +		m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
 89.1152 +		m = floor(m);
 89.1153 +
 89.1154 +		/* we never reach (1<<16) here due to the (x+1) */
 89.1155 +		/* result fits within 16 bits at maximum */
 89.1156 +
 89.1157 +		n = (int)m;		/* 16 bits here */
 89.1158 +		n >>= 4;		/* 12 bits here */
 89.1159 +		if (n&1)		/* round to nearest */
 89.1160 +			n = (n>>1)+1;
 89.1161 +		else
 89.1162 +			n = n>>1;
 89.1163 +						/* 11 bits here (rounded) */
 89.1164 +		n <<= 1;		/* 12 bits here (as in real chip) */
 89.1165 +		tl_tab[ x*2 + 0 ] = n;
 89.1166 +		tl_tab[ x*2 + 1 ] = ~tl_tab[ x*2 + 0 ]; /* this *is* different from OPL2 (verified on real YMF262) */
 89.1167 +
 89.1168 +		for (i=1; i<13; i++)
 89.1169 +		{
 89.1170 +			tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;
 89.1171 +			tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = ~tl_tab[ x*2+0 + i*2*TL_RES_LEN ];  /* this *is* different from OPL2 (verified on real YMF262) */
 89.1172 +		}
 89.1173 +	#if 0
 89.1174 +			logerror("tl %04i", x*2);
 89.1175 +			for (i=0; i<13; i++)
 89.1176 +				logerror(", [%02i] %5i", i*2, tl_tab[ x*2 +0 + i*2*TL_RES_LEN ] ); /* positive */
 89.1177 +			logerror("\n");
 89.1178 +
 89.1179 +			logerror("tl %04i", x*2);
 89.1180 +			for (i=0; i<13; i++)
 89.1181 +				logerror(", [%02i] %5i", i*2, tl_tab[ x*2 +1 + i*2*TL_RES_LEN ] ); /* negative */
 89.1182 +			logerror("\n");
 89.1183 +	#endif
 89.1184 +	}
 89.1185 +
 89.1186 +	for (i=0; i<SIN_LEN; i++)
 89.1187 +	{
 89.1188 +		/* non-standard sinus */
 89.1189 +		m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
 89.1190 +
 89.1191 +		/* we never reach zero here due to ((i*2)+1) */
 89.1192 +
 89.1193 +		if (m>0.0)
 89.1194 +			o = 8*log(1.0/m)/log(2.0);	/* convert to 'decibels' */
 89.1195 +		else
 89.1196 +			o = 8*log(-1.0/m)/log(2.0);	/* convert to 'decibels' */
 89.1197 +
 89.1198 +		o = o / (ENV_STEP/4);
 89.1199 +
 89.1200 +		n = (int)(2.0*o);
 89.1201 +		if (n&1)						/* round to nearest */
 89.1202 +			n = (n>>1)+1;
 89.1203 +		else
 89.1204 +			n = n>>1;
 89.1205 +
 89.1206 +		sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
 89.1207 +
 89.1208 +		/*logerror("YMF262.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
 89.1209 +	}
 89.1210 +
 89.1211 +	for (i=0; i<SIN_LEN; i++)
 89.1212 +	{
 89.1213 +		/* these 'pictures' represent _two_ cycles */
 89.1214 +		/* waveform 1:  __      __     */
 89.1215 +		/*             /  \____/  \____*/
 89.1216 +		/* output only first half of the sinus waveform (positive one) */
 89.1217 +
 89.1218 +		if (i & (1<<(SIN_BITS-1)) )
 89.1219 +			sin_tab[1*SIN_LEN+i] = TL_TAB_LEN;
 89.1220 +		else
 89.1221 +			sin_tab[1*SIN_LEN+i] = sin_tab[i];
 89.1222 +
 89.1223 +		/* waveform 2:  __  __  __  __ */
 89.1224 +		/*             /  \/  \/  \/  \*/
 89.1225 +		/* abs(sin) */
 89.1226 +
 89.1227 +		sin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];
 89.1228 +
 89.1229 +		/* waveform 3:  _   _   _   _  */
 89.1230 +		/*             / |_/ |_/ |_/ |_*/
 89.1231 +		/* abs(output only first quarter of the sinus waveform) */
 89.1232 +
 89.1233 +		if (i & (1<<(SIN_BITS-2)) )
 89.1234 +			sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;
 89.1235 +		else
 89.1236 +			sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];
 89.1237 +
 89.1238 +		/* waveform 4:                 */
 89.1239 +		/*             /\  ____/\  ____*/
 89.1240 +		/*               \/      \/    */
 89.1241 +		/* output whole sinus waveform in half the cycle(step=2) and output 0 on the other half of cycle */
 89.1242 +
 89.1243 +		if (i & (1<<(SIN_BITS-1)) )
 89.1244 +			sin_tab[4*SIN_LEN+i] = TL_TAB_LEN;
 89.1245 +		else
 89.1246 +			sin_tab[4*SIN_LEN+i] = sin_tab[i*2];
 89.1247 +
 89.1248 +		/* waveform 5:                 */
 89.1249 +		/*             /\/\____/\/\____*/
 89.1250 +		/*                             */
 89.1251 +		/* output abs(whole sinus) waveform in half the cycle(step=2) and output 0 on the other half of cycle */
 89.1252 +
 89.1253 +		if (i & (1<<(SIN_BITS-1)) )
 89.1254 +			sin_tab[5*SIN_LEN+i] = TL_TAB_LEN;
 89.1255 +		else
 89.1256 +			sin_tab[5*SIN_LEN+i] = sin_tab[(i*2) & (SIN_MASK>>1) ];
 89.1257 +
 89.1258 +		/* waveform 6: ____    ____    */
 89.1259 +		/*                             */
 89.1260 +		/*                 ____    ____*/
 89.1261 +		/* output maximum in half the cycle and output minimum on the other half of cycle */
 89.1262 +
 89.1263 +		if (i & (1<<(SIN_BITS-1)) )
 89.1264 +			sin_tab[6*SIN_LEN+i] = 1;	/* negative */
 89.1265 +		else
 89.1266 +			sin_tab[6*SIN_LEN+i] = 0;	/* positive */
 89.1267 +
 89.1268 +		/* waveform 7:                 */
 89.1269 +		/*             |\____  |\____  */
 89.1270 +		/*                   \|      \|*/
 89.1271 +		/* output sawtooth waveform    */
 89.1272 +
 89.1273 +		if (i & (1<<(SIN_BITS-1)) )
 89.1274 +			x = ((SIN_LEN-1)-i)*16 + 1;	/* negative: from 8177 to 1 */
 89.1275 +		else
 89.1276 +			x = i*16;	/*positive: from 0 to 8176 */
 89.1277 +
 89.1278 +		if (x > TL_TAB_LEN)
 89.1279 +			x = TL_TAB_LEN;	/* clip to the allowed range */
 89.1280 +
 89.1281 +		sin_tab[7*SIN_LEN+i] = x;
 89.1282 +
 89.1283 +		//logerror("YMF262.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );
 89.1284 +		//logerror("YMF262.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );
 89.1285 +		//logerror("YMF262.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );
 89.1286 +		//logerror("YMF262.C: sin4[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[4*SIN_LEN+i], tl_tab[sin_tab[4*SIN_LEN+i]] );
 89.1287 +		//logerror("YMF262.C: sin5[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[5*SIN_LEN+i], tl_tab[sin_tab[5*SIN_LEN+i]] );
 89.1288 +		//logerror("YMF262.C: sin6[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[6*SIN_LEN+i], tl_tab[sin_tab[6*SIN_LEN+i]] );
 89.1289 +		//logerror("YMF262.C: sin7[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[7*SIN_LEN+i], tl_tab[sin_tab[7*SIN_LEN+i]] );
 89.1290 +	}
 89.1291 +	/*logerror("YMF262.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/
 89.1292 +
 89.1293 +#ifdef SAVE_SAMPLE
 89.1294 +	sample[0]=fopen("sampsum.pcm","wb");
 89.1295 +#endif
 89.1296 +
 89.1297 +	return 1;
 89.1298 +}
 89.1299 +
 89.1300 +static void OPLCloseTable( void )
 89.1301 +{
 89.1302 +#ifdef SAVE_SAMPLE
 89.1303 +	fclose(sample[0]);
 89.1304 +#endif
 89.1305 +}
 89.1306 +
 89.1307 +
 89.1308 +
 89.1309 +static void OPL3_initalize(OPL3 *chip)
 89.1310 +{
 89.1311 +	int i;
 89.1312 +
 89.1313 +	/* frequency base */
 89.1314 +	chip->freqbase  = (chip->rate) ? ((double)chip->clock / (8.0*36)) / chip->rate  : 0;
 89.1315 +#if 0
 89.1316 +	chip->rate = (double)chip->clock / (8.0*36);
 89.1317 +	chip->freqbase  = 1.0;
 89.1318 +#endif
 89.1319 +
 89.1320 +	/* logerror("YMF262: freqbase=%f\n", chip->freqbase); */
 89.1321 +
 89.1322 +	/* Timer base time */
 89.1323 +	chip->TimerBase = attotime_mul(ATTOTIME_IN_HZ(chip->clock), 8*36);
 89.1324 +
 89.1325 +	/* make fnumber -> increment counter table */
 89.1326 +	for( i=0 ; i < 1024 ; i++ )
 89.1327 +	{
 89.1328 +		/* opn phase increment counter = 20bit */
 89.1329 +		chip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
 89.1330 +#if 0
 89.1331 +		logerror("YMF262.C: fn_tab[%4i] = %08x (dec=%8i)\n",
 89.1332 +				 i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 );
 89.1333 +#endif
 89.1334 +	}
 89.1335 +
 89.1336 +#if 0
 89.1337 +	for( i=0 ; i < 16 ; i++ )
 89.1338 +	{
 89.1339 +		logerror("YMF262.C: sl_tab[%i] = %08x\n",
 89.1340 +			i, sl_tab[i] );
 89.1341 +	}
 89.1342 +	for( i=0 ; i < 8 ; i++ )
 89.1343 +	{
 89.1344 +		int j;
 89.1345 +		logerror("YMF262.C: ksl_tab[oct=%2i] =",i);
 89.1346 +		for (j=0; j<16; j++)
 89.1347 +		{
 89.1348 +			logerror("%08x ", ksl_tab[i*16+j] );
 89.1349 +		}
 89.1350 +		logerror("\n");
 89.1351 +	}
 89.1352 +#endif
 89.1353 +
 89.1354 +
 89.1355 +	/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
 89.1356 +	/* One entry from LFO_AM_TABLE lasts for 64 samples */
 89.1357 +	chip->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * chip->freqbase;
 89.1358 +
 89.1359 +	/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
 89.1360 +	chip->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * chip->freqbase;
 89.1361 +
 89.1362 +	/*logerror ("chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\n", chip->lfo_am_inc, chip->lfo_pm_inc);*/
 89.1363 +
 89.1364 +	/* Noise generator: a step takes 1 sample */
 89.1365 +	chip->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * chip->freqbase;
 89.1366 +
 89.1367 +	chip->eg_timer_add  = (1<<EG_SH)  * chip->freqbase;
 89.1368 +	chip->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
 89.1369 +	/*logerror("YMF262init eg_timer_add=%8x eg_timer_overflow=%8x\n", chip->eg_timer_add, chip->eg_timer_overflow);*/
 89.1370 +
 89.1371 +}
 89.1372 +
 89.1373 +INLINE void FM_KEYON(OPL3_SLOT *SLOT, UINT32 key_set)
 89.1374 +{
 89.1375 +	if( !SLOT->key )
 89.1376 +	{
 89.1377 +		/* restart Phase Generator */
 89.1378 +		SLOT->Cnt = 0;
 89.1379 +		/* phase -> Attack */
 89.1380 +		SLOT->state = EG_ATT;
 89.1381 +	}
 89.1382 +	SLOT->key |= key_set;
 89.1383 +}
 89.1384 +
 89.1385 +INLINE void FM_KEYOFF(OPL3_SLOT *SLOT, UINT32 key_clr)
 89.1386 +{
 89.1387 +	if( SLOT->key )
 89.1388 +	{
 89.1389 +		SLOT->key &= key_clr;
 89.1390 +
 89.1391 +		if( !SLOT->key )
 89.1392 +		{
 89.1393 +			/* phase -> Release */
 89.1394 +			if (SLOT->state>EG_REL)
 89.1395 +				SLOT->state = EG_REL;
 89.1396 +		}
 89.1397 +	}
 89.1398 +}
 89.1399 +
 89.1400 +/* update phase increment counter of operator (also update the EG rates if necessary) */
 89.1401 +INLINE void CALC_FCSLOT(OPL3_CH *CH,OPL3_SLOT *SLOT)
 89.1402 +{
 89.1403 +	int ksr;
 89.1404 +
 89.1405 +	/* (frequency) phase increment counter */
 89.1406 +	SLOT->Incr = CH->fc * SLOT->mul;
 89.1407 +	ksr = CH->kcode >> SLOT->KSR;
 89.1408 +
 89.1409 +	if( SLOT->ksr != ksr )
 89.1410 +	{
 89.1411 +		SLOT->ksr = ksr;
 89.1412 +
 89.1413 +		/* calculate envelope generator rates */
 89.1414 +		if ((SLOT->ar + SLOT->ksr) < 16+60)
 89.1415 +		{
 89.1416 +			SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
 89.1417 +			SLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;
 89.1418 +			SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
 89.1419 +		}
 89.1420 +		else
 89.1421 +		{
 89.1422 +			SLOT->eg_sh_ar  = 0;
 89.1423 +			SLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;
 89.1424 +			SLOT->eg_sel_ar = 13*RATE_STEPS;
 89.1425 +		}
 89.1426 +		SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
 89.1427 +		SLOT->eg_m_dr   = (1<<SLOT->eg_sh_dr)-1;
 89.1428 +		SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
 89.1429 +		SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
 89.1430 +		SLOT->eg_m_rr   = (1<<SLOT->eg_sh_rr)-1;
 89.1431 +		SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
 89.1432 +	}
 89.1433 +}
 89.1434 +
 89.1435 +/* set multi,am,vib,EG-TYP,KSR,mul */
 89.1436 +INLINE void set_mul(OPL3 *chip,int slot,int v)
 89.1437 +{
 89.1438 +	OPL3_CH   *CH   = &chip->P_CH[slot/2];
 89.1439 +	OPL3_SLOT *SLOT = &CH->SLOT[slot&1];
 89.1440 +
 89.1441 +	SLOT->mul     = mul_tab[v&0x0f];
 89.1442 +	SLOT->KSR     = (v&0x10) ? 0 : 2;
 89.1443 +	SLOT->eg_type = (v&0x20);
 89.1444 +	SLOT->vib     = (v&0x40);
 89.1445 +	SLOT->AMmask  = (v&0x80) ? ~0 : 0;
 89.1446 +
 89.1447 +	if (chip->OPL3_mode & 1)
 89.1448 +	{
 89.1449 +		int chan_no = slot/2;
 89.1450 +
 89.1451 +		/* in OPL3 mode */
 89.1452 +		//DO THIS:
 89.1453 +		//if this is one of the slots of 1st channel forming up a 4-op channel
 89.1454 +		//do normal operation
 89.1455 +		//else normal 2 operator function
 89.1456 +		//OR THIS:
 89.1457 +		//if this is one of the slots of 2nd channel forming up a 4-op channel
 89.1458 +		//update it using channel data of 1st channel of a pair
 89.1459 +		//else normal 2 operator function
 89.1460 +		switch(chan_no)
 89.1461 +		{
 89.1462 +		case 0: case 1: case 2:
 89.1463 +		case 9: case 10: case 11:
 89.1464 +			if (CH->extended)
 89.1465 +			{
 89.1466 +				/* normal */
 89.1467 +				CALC_FCSLOT(CH,SLOT);
 89.1468 +			}
 89.1469 +			else
 89.1470 +			{
 89.1471 +				/* normal */
 89.1472 +				CALC_FCSLOT(CH,SLOT);
 89.1473 +			}
 89.1474 +		break;
 89.1475 +		case 3: case 4: case 5:
 89.1476 +		case 12: case 13: case 14:
 89.1477 +			if ((CH-3)->extended)
 89.1478 +			{
 89.1479 +				/* update this SLOT using frequency data for 1st channel of a pair */
 89.1480 +				CALC_FCSLOT(CH-3,SLOT);
 89.1481 +			}
 89.1482 +			else
 89.1483 +			{
 89.1484 +				/* normal */
 89.1485 +				CALC_FCSLOT(CH,SLOT);
 89.1486 +			}
 89.1487 +		break;
 89.1488 +		default:
 89.1489 +				/* normal */
 89.1490 +				CALC_FCSLOT(CH,SLOT);
 89.1491 +		break;
 89.1492 +		}
 89.1493 +	}
 89.1494 +	else
 89.1495 +	{
 89.1496 +		/* in OPL2 mode */
 89.1497 +		CALC_FCSLOT(CH,SLOT);
 89.1498 +	}
 89.1499 +}
 89.1500 +
 89.1501 +/* set ksl & tl */
 89.1502 +INLINE void set_ksl_tl(OPL3 *chip,int slot,int v)
 89.1503 +{
 89.1504 +	OPL3_CH   *CH   = &chip->P_CH[slot/2];
 89.1505 +	OPL3_SLOT *SLOT = &CH->SLOT[slot&1];
 89.1506 +
 89.1507 +	int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
 89.1508 +
 89.1509 +	SLOT->ksl = ksl ? 3-ksl : 31;
 89.1510 +	SLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
 89.1511 +
 89.1512 +	if (chip->OPL3_mode & 1)
 89.1513 +	{
 89.1514 +		int chan_no = slot/2;
 89.1515 +
 89.1516 +		/* in OPL3 mode */
 89.1517 +		//DO THIS:
 89.1518 +		//if this is one of the slots of 1st channel forming up a 4-op channel
 89.1519 +		//do normal operation
 89.1520 +		//else normal 2 operator function
 89.1521 +		//OR THIS:
 89.1522 +		//if this is one of the slots of 2nd channel forming up a 4-op channel
 89.1523 +		//update it using channel data of 1st channel of a pair
 89.1524 +		//else normal 2 operator function
 89.1525 +		switch(chan_no)
 89.1526 +		{
 89.1527 +		case 0: case 1: case 2:
 89.1528 +		case 9: case 10: case 11:
 89.1529 +			if (CH->extended)
 89.1530 +			{
 89.1531 +				/* normal */
 89.1532 +				SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 89.1533 +			}
 89.1534 +			else
 89.1535 +			{
 89.1536 +				/* normal */
 89.1537 +				SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 89.1538 +			}
 89.1539 +		break;
 89.1540 +		case 3: case 4: case 5:
 89.1541 +		case 12: case 13: case 14:
 89.1542 +			if ((CH-3)->extended)
 89.1543 +			{
 89.1544 +				/* update this SLOT using frequency data for 1st channel of a pair */
 89.1545 +				SLOT->TLL = SLOT->TL + ((CH-3)->ksl_base>>SLOT->ksl);
 89.1546 +			}
 89.1547 +			else
 89.1548 +			{
 89.1549 +				/* normal */
 89.1550 +				SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 89.1551 +			}
 89.1552 +		break;
 89.1553 +		default:
 89.1554 +				/* normal */
 89.1555 +				SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 89.1556 +		break;
 89.1557 +		}
 89.1558 +	}
 89.1559 +	else
 89.1560 +	{
 89.1561 +		/* in OPL2 mode */
 89.1562 +		SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
 89.1563 +	}
 89.1564 +
 89.1565 +}
 89.1566 +
 89.1567 +/* set attack rate & decay rate  */
 89.1568 +INLINE void set_ar_dr(OPL3 *chip,int slot,int v)
 89.1569 +{
 89.1570 +	OPL3_CH   *CH   = &chip->P_CH[slot/2];
 89.1571 +	OPL3_SLOT *SLOT = &CH->SLOT[slot&1];
 89.1572 +
 89.1573 +	SLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;
 89.1574 +
 89.1575 +	if ((SLOT->ar + SLOT->ksr) < 16+60) /* verified on real YMF262 - all 15 x rates take "zero" time */
 89.1576 +	{
 89.1577 +		SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
 89.1578 +		SLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;
 89.1579 +		SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
 89.1580 +	}
 89.1581 +	else
 89.1582 +	{
 89.1583 +		SLOT->eg_sh_ar  = 0;
 89.1584 +		SLOT->eg_m_ar   = (1<<SLOT->eg_sh_ar)-1;
 89.1585 +		SLOT->eg_sel_ar = 13*RATE_STEPS;
 89.1586 +	}
 89.1587 +
 89.1588 +	SLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
 89.1589 +	SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
 89.1590 +	SLOT->eg_m_dr   = (1<<SLOT->eg_sh_dr)-1;
 89.1591 +	SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
 89.1592 +}
 89.1593 +
 89.1594 +/* set sustain level & release rate */
 89.1595 +INLINE void set_sl_rr(OPL3 *chip,int slot,int v)
 89.1596 +{
 89.1597 +	OPL3_CH   *CH   = &chip->P_CH[slot/2];
 89.1598 +	OPL3_SLOT *SLOT = &CH->SLOT[slot&1];
 89.1599 +
 89.1600 +	SLOT->sl  = sl_tab[ v>>4 ];
 89.1601 +
 89.1602 +	SLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
 89.1603 +	SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
 89.1604 +	SLOT->eg_m_rr   = (1<<SLOT->eg_sh_rr)-1;
 89.1605 +	SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
 89.1606 +}
 89.1607 +
 89.1608 +
 89.1609 +static void update_channels(OPL3 *chip, OPL3_CH *CH)
 89.1610 +{
 89.1611 +	/* update channel passed as a parameter and a channel at CH+=3; */
 89.1612 +	if (CH->extended)
 89.1613 +	{	/* we've just switched to combined 4 operator mode */
 89.1614 +
 89.1615 +	}
 89.1616 +	else
 89.1617 +	{	/* we've just switched to normal 2 operator mode */
 89.1618 +
 89.1619 +	}
 89.1620 +
 89.1621 +}
 89.1622 +
 89.1623 +/* write a value v to register r on OPL chip */
 89.1624 +static void OPL3WriteReg(OPL3 *chip, int r, int v)
 89.1625 +{
 89.1626 +	OPL3_CH *CH;
 89.1627 +	unsigned int ch_offset = 0;
 89.1628 +	int slot;
 89.1629 +	int block_fnum;
 89.1630 +
 89.1631 +
 89.1632 +
 89.1633 +	if (LOG_CYM_FILE && (cymfile) && ((r&255)!=0) && (r!=255) )
 89.1634 +	{
 89.1635 +		if (r>0xff)
 89.1636 +			fputc( (unsigned char)0xff, cymfile );/*mark writes to second register set*/
 89.1637 +
 89.1638 +		fputc( (unsigned char)r&0xff, cymfile );
 89.1639 +		fputc( (unsigned char)v, cymfile );
 89.1640 +	}
 89.1641 +
 89.1642 +	if(r&0x100)
 89.1643 +	{
 89.1644 +		switch(r)
 89.1645 +		{
 89.1646 +		case 0x101:	/* test register */
 89.1647 +			return;
 89.1648 +
 89.1649 +		case 0x104:	/* 6 channels enable */
 89.1650 +			{
 89.1651 +				UINT8 prev;
 89.1652 +
 89.1653 +				CH = &chip->P_CH[0];	/* channel 0 */
 89.1654 +				prev = CH->extended;
 89.1655 +				CH->extended = (v>>0) & 1;
 89.1656 +				if(prev != CH->extended)
 89.1657 +					update_channels(chip, CH);
 89.1658 +				CH++;					/* channel 1 */
 89.1659 +				prev = CH->extended;
 89.1660 +				CH->extended = (v>>1) & 1;
 89.1661 +				if(prev != CH->extended)
 89.1662 +					update_channels(chip, CH);
 89.1663 +				CH++;					/* channel 2 */
 89.1664 +				prev = CH->extended;
 89.1665 +				CH->extended = (v>>2) & 1;
 89.1666 +				if(prev != CH->extended)
 89.1667 +					update_channels(chip, CH);
 89.1668 +
 89.1669 +
 89.1670 +				CH = &chip->P_CH[9];	/* channel 9 */
 89.1671 +				prev = CH->extended;
 89.1672 +				CH->extended = (v>>3) & 1;
 89.1673 +				if(prev != CH->extended)
 89.1674 +					update_channels(chip, CH);
 89.1675 +				CH++;					/* channel 10 */
 89.1676 +				prev = CH->extended;
 89.1677 +				CH->extended = (v>>4) & 1;
 89.1678 +				if(prev != CH->extended)
 89.1679 +					update_channels(chip, CH);
 89.1680 +				CH++;					/* channel 11 */
 89.1681 +				prev = CH->extended;
 89.1682 +				CH->extended = (v>>5) & 1;
 89.1683 +				if(prev != CH->extended)
 89.1684 +					update_channels(chip, CH);
 89.1685 +
 89.1686 +			}
 89.1687 +			return;
 89.1688 +
 89.1689 +		case 0x105:	/* OPL3 extensions enable register */
 89.1690 +
 89.1691 +			chip->OPL3_mode = v&0x01;	/* OPL3 mode when bit0=1 otherwise it is OPL2 mode */
 89.1692 +
 89.1693 +			/* following behaviour was tested on real YMF262,
 89.1694 +            switching OPL3/OPL2 modes on the fly:
 89.1695 +             - does not change the waveform previously selected (unless when ....)
 89.1696 +             - does not update CH.A, CH.B, CH.C and CH.D output selectors (registers c0-c8) (unless when ....)
 89.1697 +             - does not disable channels 9-17 on OPL3->OPL2 switch
 89.1698 +             - does not switch 4 operator channels back to 2 operator channels
 89.1699 +            */
 89.1700 +
 89.1701 +			return;
 89.1702 +
 89.1703 +		default:
 89.1704 +			if (r < 0x120)
 89.1705 +				pclog("YMF262: write to unknown register (set#2): %03x value=%02x\n",r,v);
 89.1706 +		break;
 89.1707 +		}
 89.1708 +
 89.1709 +		ch_offset = 9;	/* register page #2 starts from channel 9 (counting from 0) */
 89.1710 +	}
 89.1711 +
 89.1712 +	/* adjust bus to 8 bits */
 89.1713 +	r &= 0xff;
 89.1714 +	v &= 0xff;
 89.1715 +
 89.1716 +
 89.1717 +	switch(r&0xe0)
 89.1718 +	{
 89.1719 +	case 0x00:	/* 00-1f:control */
 89.1720 +		switch(r&0x1f)
 89.1721 +		{
 89.1722 +		case 0x01:	/* test register */
 89.1723 +		break;
 89.1724 +		case 0x02:	/* Timer 1 */
 89.1725 +			chip->T[0] = (256-v)*4;
 89.1726 +		break;
 89.1727 +		case 0x03:	/* Timer 2 */
 89.1728 +			chip->T[1] = (256-v)*16;
 89.1729 +		break;
 89.1730 +		case 0x04:	/* IRQ clear / mask and Timer enable */
 89.1731 +			if(v&0x80)
 89.1732 +			{	/* IRQ flags clear */
 89.1733 +				OPL3_STATUS_RESET(chip,0x60);
 89.1734 +			}
 89.1735 +			else
 89.1736 +			{	/* set IRQ mask ,timer enable */
 89.1737 +				UINT8 st1 = v & 1;
 89.1738 +				UINT8 st2 = (v>>1) & 1;
 89.1739 +
 89.1740 +				/* IRQRST,T1MSK,t2MSK,x,x,x,ST2,ST1 */
 89.1741 +				OPL3_STATUS_RESET(chip, v & 0x60);
 89.1742 +				OPL3_STATUSMASK_SET(chip, (~v) & 0x60 );
 89.1743 +
 89.1744 +				/* timer 2 */
 89.1745 +				if(chip->st[1] != st2)
 89.1746 +				{
 89.1747 +					attotime period = st2 ? attotime_mul(chip->TimerBase, chip->T[1]) : attotime_zero;
 89.1748 +					chip->st[1] = st2;
 89.1749 +					if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,1,period);
 89.1750 +				}
 89.1751 +				/* timer 1 */
 89.1752 +				if(chip->st[0] != st1)
 89.1753 +				{
 89.1754 +					attotime period = st1 ? attotime_mul(chip->TimerBase, chip->T[0]) : attotime_zero;
 89.1755 +					chip->st[0] = st1;
 89.1756 +					if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,0,period);
 89.1757 +				}
 89.1758 +			}
 89.1759 +		break;
 89.1760 +		case 0x08:	/* x,NTS,x,x, x,x,x,x */
 89.1761 +			chip->nts = v;
 89.1762 +		break;
 89.1763 +
 89.1764 +		default:
 89.1765 +			pclog("YMF262: write to unknown register: %02x value=%02x\n",r,v);
 89.1766 +		break;
 89.1767 +		}
 89.1768 +		break;
 89.1769 +	case 0x20:	/* am ON, vib ON, ksr, eg_type, mul */
 89.1770 +		slot = slot_array[r&0x1f];
 89.1771 +		if(slot < 0) return;
 89.1772 +		set_mul(chip, slot + ch_offset*2, v);
 89.1773 +	break;
 89.1774 +	case 0x40:
 89.1775 +		slot = slot_array[r&0x1f];
 89.1776 +		if(slot < 0) return;
 89.1777 +		set_ksl_tl(chip, slot + ch_offset*2, v);
 89.1778 +	break;
 89.1779 +	case 0x60:
 89.1780 +		slot = slot_array[r&0x1f];
 89.1781 +		if(slot < 0) return;
 89.1782 +		set_ar_dr(chip, slot + ch_offset*2, v);
 89.1783 +	break;
 89.1784 +	case 0x80:
 89.1785 +		slot = slot_array[r&0x1f];
 89.1786 +		if(slot < 0) return;
 89.1787 +		set_sl_rr(chip, slot + ch_offset*2, v);
 89.1788 +	break;
 89.1789 +	case 0xa0:
 89.1790 +		if (r == 0xbd)			/* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
 89.1791 +		{
 89.1792 +			if (ch_offset != 0)	/* 0xbd register is present in set #1 only */
 89.1793 +				return;
 89.1794 +
 89.1795 +			chip->lfo_am_depth = v & 0x80;
 89.1796 +			chip->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
 89.1797 +
 89.1798 +			chip->rhythm = v&0x3f;
 89.1799 +
 89.1800 +			if(chip->rhythm&0x20)
 89.1801 +			{
 89.1802 +				/* BD key on/off */
 89.1803 +				if(v&0x10)
 89.1804 +				{
 89.1805 +					FM_KEYON (&chip->P_CH[6].SLOT[SLOT1], 2);
 89.1806 +					FM_KEYON (&chip->P_CH[6].SLOT[SLOT2], 2);
 89.1807 +				}
 89.1808 +				else
 89.1809 +				{
 89.1810 +					FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2);
 89.1811 +					FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2);
 89.1812 +				}
 89.1813 +				/* HH key on/off */
 89.1814 +				if(v&0x01) FM_KEYON (&chip->P_CH[7].SLOT[SLOT1], 2);
 89.1815 +				else       FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2);
 89.1816 +				/* SD key on/off */
 89.1817 +				if(v&0x08) FM_KEYON (&chip->P_CH[7].SLOT[SLOT2], 2);
 89.1818 +				else       FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2);
 89.1819 +				/* TOM key on/off */
 89.1820 +				if(v&0x04) FM_KEYON (&chip->P_CH[8].SLOT[SLOT1], 2);
 89.1821 +				else       FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2);
 89.1822 +				/* TOP-CY key on/off */
 89.1823 +				if(v&0x02) FM_KEYON (&chip->P_CH[8].SLOT[SLOT2], 2);
 89.1824 +				else       FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2);
 89.1825 +			}
 89.1826 +			else
 89.1827 +			{
 89.1828 +				/* BD key off */
 89.1829 +				FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2);
 89.1830 +				FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2);
 89.1831 +				/* HH key off */
 89.1832 +				FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2);
 89.1833 +				/* SD key off */
 89.1834 +				FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2);
 89.1835 +				/* TOM key off */
 89.1836 +				FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2);
 89.1837 +				/* TOP-CY off */
 89.1838 +				FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2);
 89.1839 +			}
 89.1840 +			return;
 89.1841 +		}
 89.1842 +
 89.1843 +		/* keyon,block,fnum */
 89.1844 +		if( (r&0x0f) > 8) return;
 89.1845 +		CH = &chip->P_CH[(r&0x0f) + ch_offset];
 89.1846 +
 89.1847 +		if(!(r&0x10))
 89.1848 +		{	/* a0-a8 */
 89.1849 +			block_fnum  = (CH->block_fnum&0x1f00) | v;
 89.1850 +		}
 89.1851 +		else
 89.1852 +		{	/* b0-b8 */
 89.1853 +			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
 89.1854 +
 89.1855 +			if (chip->OPL3_mode & 1)
 89.1856 +			{
 89.1857 +				int chan_no = (r&0x0f) + ch_offset;
 89.1858 +
 89.1859 +				/* in OPL3 mode */
 89.1860 +				//DO THIS:
 89.1861 +				//if this is 1st channel forming up a 4-op channel
 89.1862 +				//ALSO keyon/off slots of 2nd channel forming up 4-op channel
 89.1863 +				//else normal 2 operator function keyon/off
 89.1864 +				//OR THIS:
 89.1865 +				//if this is 2nd channel forming up 4-op channel just do nothing
 89.1866 +				//else normal 2 operator function keyon/off
 89.1867 +				switch(chan_no)
 89.1868 +				{
 89.1869 +				case 0: case 1: case 2:
 89.1870 +				case 9: case 10: case 11:
 89.1871 +					if (CH->extended)
 89.1872 +					{
 89.1873 +						//if this is 1st channel forming up a 4-op channel
 89.1874 +						//ALSO keyon/off slots of 2nd channel forming up 4-op channel
 89.1875 +						if(v&0x20)
 89.1876 +						{
 89.1877 +							FM_KEYON (&CH->SLOT[SLOT1], 1);
 89.1878 +							FM_KEYON (&CH->SLOT[SLOT2], 1);
 89.1879 +							FM_KEYON (&(CH+3)->SLOT[SLOT1], 1);
 89.1880 +							FM_KEYON (&(CH+3)->SLOT[SLOT2], 1);
 89.1881 +						}
 89.1882 +						else
 89.1883 +						{
 89.1884 +							FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 89.1885 +							FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 89.1886 +							FM_KEYOFF(&(CH+3)->SLOT[SLOT1],~1);
 89.1887 +							FM_KEYOFF(&(CH+3)->SLOT[SLOT2],~1);
 89.1888 +						}
 89.1889 +					}
 89.1890 +					else
 89.1891 +					{
 89.1892 +						//else normal 2 operator function keyon/off
 89.1893 +						if(v&0x20)
 89.1894 +						{
 89.1895 +							FM_KEYON (&CH->SLOT[SLOT1], 1);
 89.1896 +							FM_KEYON (&CH->SLOT[SLOT2], 1);
 89.1897 +						}
 89.1898 +						else
 89.1899 +						{
 89.1900 +							FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 89.1901 +							FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 89.1902 +						}
 89.1903 +					}
 89.1904 +				break;
 89.1905 +
 89.1906 +				case 3: case 4: case 5:
 89.1907 +				case 12: case 13: case 14:
 89.1908 +					if ((CH-3)->extended)
 89.1909 +					{
 89.1910 +						//if this is 2nd channel forming up 4-op channel just do nothing
 89.1911 +					}
 89.1912 +					else
 89.1913 +					{
 89.1914 +						//else normal 2 operator function keyon/off
 89.1915 +						if(v&0x20)
 89.1916 +						{
 89.1917 +							FM_KEYON (&CH->SLOT[SLOT1], 1);
 89.1918 +							FM_KEYON (&CH->SLOT[SLOT2], 1);
 89.1919 +						}
 89.1920 +						else
 89.1921 +						{
 89.1922 +							FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 89.1923 +							FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 89.1924 +						}
 89.1925 +					}
 89.1926 +				break;
 89.1927 +
 89.1928 +				default:
 89.1929 +					if(v&0x20)
 89.1930 +					{
 89.1931 +						FM_KEYON (&CH->SLOT[SLOT1], 1);
 89.1932 +						FM_KEYON (&CH->SLOT[SLOT2], 1);
 89.1933 +					}
 89.1934 +					else
 89.1935 +					{
 89.1936 +						FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 89.1937 +						FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 89.1938 +					}
 89.1939 +				break;
 89.1940 +				}
 89.1941 +			}
 89.1942 +			else
 89.1943 +			{
 89.1944 +				if(v&0x20)
 89.1945 +				{
 89.1946 +					FM_KEYON (&CH->SLOT[SLOT1], 1);
 89.1947 +					FM_KEYON (&CH->SLOT[SLOT2], 1);
 89.1948 +				}
 89.1949 +				else
 89.1950 +				{
 89.1951 +					FM_KEYOFF(&CH->SLOT[SLOT1],~1);
 89.1952 +					FM_KEYOFF(&CH->SLOT[SLOT2],~1);
 89.1953 +				}
 89.1954 +			}
 89.1955 +		}
 89.1956 +		/* update */
 89.1957 +		if(CH->block_fnum != block_fnum)
 89.1958 +		{
 89.1959 +			UINT8 block  = block_fnum >> 10;
 89.1960 +
 89.1961 +			CH->block_fnum = block_fnum;
 89.1962 +
 89.1963 +			CH->ksl_base = ksl_tab[block_fnum>>6];
 89.1964 +			CH->fc       = chip->fn_tab[block_fnum&0x03ff] >> (7-block);
 89.1965 +
 89.1966 +			/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
 89.1967 +			CH->kcode    = (CH->block_fnum&0x1c00)>>9;
 89.1968 +
 89.1969 +			/* the info below is actually opposite to what is stated in the Manuals (verifed on real YMF262) */
 89.1970 +			/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */
 89.1971 +			/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
 89.1972 +			if (chip->nts&0x40)
 89.1973 +				CH->kcode |= (CH->block_fnum&0x100)>>8;	/* notesel == 1 */
 89.1974 +			else
 89.1975 +				CH->kcode |= (CH->block_fnum&0x200)>>9;	/* notesel == 0 */
 89.1976 +
 89.1977 +			if (chip->OPL3_mode & 1)
 89.1978 +			{
 89.1979 +				int chan_no = (r&0x0f) + ch_offset;
 89.1980 +				/* in OPL3 mode */
 89.1981 +				//DO THIS:
 89.1982 +				//if this is 1st channel forming up a 4-op channel
 89.1983 +				//ALSO update slots of 2nd channel forming up 4-op channel
 89.1984 +				//else normal 2 operator function keyon/off
 89.1985 +				//OR THIS:
 89.1986 +				//if this is 2nd channel forming up 4-op channel just do nothing
 89.1987 +				//else normal 2 operator function keyon/off
 89.1988 +				switch(chan_no)
 89.1989 +				{
 89.1990 +				case 0: case 1: case 2:
 89.1991 +				case 9: case 10: case 11:
 89.1992 +					if (CH->extended)
 89.1993 +					{
 89.1994 +						//if this is 1st channel forming up a 4-op channel
 89.1995 +						//ALSO update slots of 2nd channel forming up 4-op channel
 89.1996 +
 89.1997 +						/* refresh Total Level in FOUR SLOTs of this channel and channel+3 using data from THIS channel */
 89.1998 +						CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 89.1999 +						CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 89.2000 +						(CH+3)->SLOT[SLOT1].TLL = (CH+3)->SLOT[SLOT1].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT1].ksl);
 89.2001 +						(CH+3)->SLOT[SLOT2].TLL = (CH+3)->SLOT[SLOT2].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT2].ksl);
 89.2002 +
 89.2003 +						/* refresh frequency counter in FOUR SLOTs of this channel and channel+3 using data from THIS channel */
 89.2004 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 89.2005 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 89.2006 +						CALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT1]);
 89.2007 +						CALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT2]);
 89.2008 +					}
 89.2009 +					else
 89.2010 +					{
 89.2011 +						//else normal 2 operator function
 89.2012 +						/* refresh Total Level in both SLOTs of this channel */
 89.2013 +						CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 89.2014 +						CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 89.2015 +
 89.2016 +						/* refresh frequency counter in both SLOTs of this channel */
 89.2017 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 89.2018 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 89.2019 +					}
 89.2020 +				break;
 89.2021 +
 89.2022 +				case 3: case 4: case 5:
 89.2023 +				case 12: case 13: case 14:
 89.2024 +					if ((CH-3)->extended)
 89.2025 +					{
 89.2026 +						//if this is 2nd channel forming up 4-op channel just do nothing
 89.2027 +					}
 89.2028 +					else
 89.2029 +					{
 89.2030 +						//else normal 2 operator function
 89.2031 +						/* refresh Total Level in both SLOTs of this channel */
 89.2032 +						CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 89.2033 +						CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 89.2034 +
 89.2035 +						/* refresh frequency counter in both SLOTs of this channel */
 89.2036 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 89.2037 +						CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 89.2038 +					}
 89.2039 +				break;
 89.2040 +
 89.2041 +				default:
 89.2042 +					/* refresh Total Level in both SLOTs of this channel */
 89.2043 +					CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 89.2044 +					CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 89.2045 +
 89.2046 +					/* refresh frequency counter in both SLOTs of this channel */
 89.2047 +					CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 89.2048 +					CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 89.2049 +				break;
 89.2050 +				}
 89.2051 +			}
 89.2052 +			else
 89.2053 +			{
 89.2054 +				/* in OPL2 mode */
 89.2055 +
 89.2056 +				/* refresh Total Level in both SLOTs of this channel */
 89.2057 +				CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
 89.2058 +				CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
 89.2059 +
 89.2060 +				/* refresh frequency counter in both SLOTs of this channel */
 89.2061 +				CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
 89.2062 +				CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
 89.2063 +			}
 89.2064 +		}
 89.2065 +	break;
 89.2066 +
 89.2067 +	case 0xc0:
 89.2068 +		/* CH.D, CH.C, CH.B, CH.A, FB(3bits), C */
 89.2069 +		if( (r&0xf) > 8) return;
 89.2070 +
 89.2071 +		CH = &chip->P_CH[(r&0xf) + ch_offset];
 89.2072 +
 89.2073 +		if( chip->OPL3_mode & 1 )
 89.2074 +		{
 89.2075 +			int base = ((r&0xf) + ch_offset) * 4;
 89.2076 +
 89.2077 +			/* OPL3 mode */
 89.2078 +			chip->pan[ base    ] = (v & 0x10) ? ~0 : 0;	/* ch.A */
 89.2079 +			chip->pan[ base +1 ] = (v & 0x20) ? ~0 : 0;	/* ch.B */
 89.2080 +			chip->pan[ base +2 ] = (v & 0x40) ? ~0 : 0;	/* ch.C */
 89.2081 +			chip->pan[ base +3 ] = (v & 0x80) ? ~0 : 0;	/* ch.D */
 89.2082 +		}
 89.2083 +		else
 89.2084 +		{
 89.2085 +			int base = ((r&0xf) + ch_offset) * 4;
 89.2086 +
 89.2087 +			/* OPL2 mode - always enabled */
 89.2088 +			chip->pan[ base    ] = ~0;		/* ch.A */
 89.2089 +			chip->pan[ base +1 ] = ~0;		/* ch.B */
 89.2090 +			chip->pan[ base +2 ] = ~0;		/* ch.C */
 89.2091 +			chip->pan[ base +3 ] = ~0;		/* ch.D */
 89.2092 +		}
 89.2093 +
 89.2094 +		chip->pan_ctrl_value[ (r&0xf) + ch_offset ] = v;	/* store control value for OPL3/OPL2 mode switching on the fly */
 89.2095 +
 89.2096 +		CH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
 89.2097 +		CH->SLOT[SLOT1].CON = v&1;
 89.2098 +
 89.2099 +		if( chip->OPL3_mode & 1 )
 89.2100 +		{
 89.2101 +			int chan_no = (r&0x0f) + ch_offset;
 89.2102 +
 89.2103 +			switch(chan_no)
 89.2104 +			{
 89.2105 +			case 0: case 1: case 2:
 89.2106 +			case 9: case 10: case 11:
 89.2107 +				if (CH->extended)
 89.2108 +				{
 89.2109 +					UINT8 conn = (CH->SLOT[SLOT1].CON<<1) || ((CH+3)->SLOT[SLOT1].CON<<0);
 89.2110 +					switch(conn)
 89.2111 +					{
 89.2112 +					case 0:
 89.2113 +						/* 1 -> 2 -> 3 -> 4 - out */
 89.2114 +
 89.2115 +						CH->SLOT[SLOT1].connect = &phase_modulation;
 89.2116 +						CH->SLOT[SLOT2].connect = &phase_modulation2;
 89.2117 +						(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
 89.2118 +						(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
 89.2119 +					break;
 89.2120 +					case 1:
 89.2121 +						/* 1 -> 2 -\
 89.2122 +                           3 -> 4 -+- out */
 89.2123 +
 89.2124 +						CH->SLOT[SLOT1].connect = &phase_modulation;
 89.2125 +						CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
 89.2126 +						(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
 89.2127 +						(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
 89.2128 +					break;
 89.2129 +					case 2:
 89.2130 +						/* 1 -----------\
 89.2131 +                           2 -> 3 -> 4 -+- out */
 89.2132 +
 89.2133 +						CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
 89.2134 +						CH->SLOT[SLOT2].connect = &phase_modulation2;
 89.2135 +						(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
 89.2136 +						(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
 89.2137 +					break;
 89.2138 +					case 3:
 89.2139 +						/* 1 ------\
 89.2140 +                           2 -> 3 -+- out
 89.2141 +                           4 ------/     */
 89.2142 +						CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
 89.2143 +						CH->SLOT[SLOT2].connect = &phase_modulation2;
 89.2144 +						(CH+3)->SLOT[SLOT1].connect = &chanout[ chan_no + 3 ];
 89.2145 +						(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
 89.2146 +					break;
 89.2147 +					}
 89.2148 +				}
 89.2149 +				else
 89.2150 +				{
 89.2151 +					/* 2 operators mode */
 89.2152 +					CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
 89.2153 +					CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
 89.2154 +				}
 89.2155 +			break;
 89.2156 +
 89.2157 +			case 3: case 4: case 5:
 89.2158 +			case 12: case 13: case 14:
 89.2159 +				if ((CH-3)->extended)
 89.2160 +				{
 89.2161 +					UINT8 conn = ((CH-3)->SLOT[SLOT1].CON<<1) || (CH->SLOT[SLOT1].CON<<0);
 89.2162 +					switch(conn)
 89.2163 +					{
 89.2164 +					case 0:
 89.2165 +						/* 1 -> 2 -> 3 -> 4 - out */
 89.2166 +
 89.2167 +						(CH-3)->SLOT[SLOT1].connect = &phase_modulation;
 89.2168 +						(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
 89.2169 +						CH->SLOT[SLOT1].connect = &phase_modulation;
 89.2170 +						CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
 89.2171 +					break;
 89.2172 +					case 1:
 89.2173 +						/* 1 -> 2 -\
 89.2174 +                           3 -> 4 -+- out */
 89.2175 +
 89.2176 +						(CH-3)->SLOT[SLOT1].connect = &phase_modulation;
 89.2177 +						(CH-3)->SLOT[SLOT2].connect = &chanout[ chan_no - 3 ];
 89.2178 +						CH->SLOT[SLOT1].connect = &phase_modulation;
 89.2179 +						CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
 89.2180 +					break;
 89.2181 +					case 2:
 89.2182 +						/* 1 -----------\
 89.2183 +                           2 -> 3 -> 4 -+- out */
 89.2184 +
 89.2185 +						(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];
 89.2186 +						(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
 89.2187 +						CH->SLOT[SLOT1].connect = &phase_modulation;
 89.2188 +						CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
 89.2189 +					break;
 89.2190 +					case 3:
 89.2191 +						/* 1 ------\
 89.2192 +                           2 -> 3 -+- out
 89.2193 +                           4 ------/     */
 89.2194 +						(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];
 89.2195 +						(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
 89.2196 +						CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
 89.2197 +						CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
 89.2198 +					break;
 89.2199 +					}
 89.2200 +				}
 89.2201 +				else
 89.2202 +				{
 89.2203 +					/* 2 operators mode */
 89.2204 +					CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
 89.2205 +					CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
 89.2206 +				}
 89.2207 +			break;
 89.2208 +
 89.2209 +			default:
 89.2210 +					/* 2 operators mode */
 89.2211 +					CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
 89.2212 +					CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
 89.2213 +			break;
 89.2214 +			}
 89.2215 +		}
 89.2216 +		else
 89.2217 +		{
 89.2218 +			/* OPL2 mode - always 2 operators mode */
 89.2219 +			CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
 89.2220 +			CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
 89.2221 +		}
 89.2222 +	break;
 89.2223 +
 89.2224 +	case 0xe0: /* waveform select */
 89.2225 +		slot = slot_array[r&0x1f];
 89.2226 +		if(slot < 0) return;
 89.2227 +
 89.2228 +		slot += ch_offset*2;
 89.2229 +
 89.2230 +		CH = &chip->P_CH[slot/2];
 89.2231 +
 89.2232 +
 89.2233 +		/* store 3-bit value written regardless of current OPL2 or OPL3 mode... (verified on real YMF262) */
 89.2234 +		v &= 7;
 89.2235 +		CH->SLOT[slot&1].waveform_number = v;
 89.2236 +
 89.2237 +		/* ... but select only waveforms 0-3 in OPL2 mode */
 89.2238 +		if( !(chip->OPL3_mode & 1) )
 89.2239 +		{
 89.2240 +			v &= 3; /* we're in OPL2 mode */
 89.2241 +		}
 89.2242 +		CH->SLOT[slot&1].wavetable = v * SIN_LEN;
 89.2243 +	break;
 89.2244 +	}
 89.2245 +}
 89.2246 +
 89.2247 +static TIMER_CALLBACK( cymfile_callback )
 89.2248 +{
 89.2249 +	if (cymfile)
 89.2250 +	{
 89.2251 +		fputc( (unsigned char)0, cymfile );
 89.2252 +	}
 89.2253 +}
 89.2254 +
 89.2255 +/* lock/unlock for common table */
 89.2256 +static int OPL3_LockTable(running_device *device)
 89.2257 +{
 89.2258 +	num_lock++;
 89.2259 +	if(num_lock>1) return 0;
 89.2260 +
 89.2261 +	/* first time */
 89.2262 +
 89.2263 +	cur_chip = NULL;
 89.2264 +
 89.2265 +	if( !init_tables() )
 89.2266 +	{
 89.2267 +		num_lock--;
 89.2268 +		return -1;
 89.2269 +	}
 89.2270 +#if 0
 89.2271 +	if (LOG_CYM_FILE)
 89.2272 +	{
 89.2273 +		cymfile = fopen("ymf262_.cym","wb");
 89.2274 +		if (cymfile)
 89.2275 +			timer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); /*110 Hz pulse timer*/
 89.2276 +		else
 89.2277 +			logerror("Could not create ymf262_.cym file\n");
 89.2278 +	}
 89.2279 +#endif
 89.2280 +	return 0;
 89.2281 +}
 89.2282 +
 89.2283 +static void OPL3_UnLockTable(void)
 89.2284 +{
 89.2285 +	if(num_lock) num_lock--;
 89.2286 +	if(num_lock) return;
 89.2287 +
 89.2288 +	/* last time */
 89.2289 +
 89.2290 +	cur_chip = NULL;
 89.2291 +	OPLCloseTable();
 89.2292 +
 89.2293 +	if (LOG_CYM_FILE)
 89.2294 +		fclose (cymfile);
 89.2295 +	cymfile = NULL;
 89.2296 +}
 89.2297 +
 89.2298 +static void OPL3ResetChip(OPL3 *chip)
 89.2299 +{
 89.2300 +	int c,s;
 89.2301 +
 89.2302 +	chip->eg_timer = 0;
 89.2303 +	chip->eg_cnt   = 0;
 89.2304 +
 89.2305 +	chip->noise_rng = 1;	/* noise shift register */
 89.2306 +	chip->nts       = 0;	/* note split */
 89.2307 +	OPL3_STATUS_RESET(chip,0x60);
 89.2308 +
 89.2309 +	/* reset with register write */
 89.2310 +	OPL3WriteReg(chip,0x01,0); /* test register */
 89.2311 +	OPL3WriteReg(chip,0x02,0); /* Timer1 */
 89.2312 +	OPL3WriteReg(chip,0x03,0); /* Timer2 */
 89.2313 +	OPL3WriteReg(chip,0x04,0); /* IRQ mask clear */
 89.2314 +
 89.2315 +
 89.2316 +//FIX IT  registers 101, 104 and 105
 89.2317 +
 89.2318 +
 89.2319 +//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
 89.2320 +	for(c = 0xff ; c >= 0x20 ; c-- )
 89.2321 +		OPL3WriteReg(chip,c,0);
 89.2322 +//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers)
 89.2323 +	for(c = 0x1ff ; c >= 0x120 ; c-- )
 89.2324 +		OPL3WriteReg(chip,c,0);
 89.2325 +
 89.2326 +
 89.2327 +
 89.2328 +	/* reset operator parameters */
 89.2329 +	for( c = 0 ; c < 9*2 ; c++ )
 89.2330 +	{
 89.2331 +		OPL3_CH *CH = &chip->P_CH[c];
 89.2332 +		for(s = 0 ; s < 2 ; s++ )
 89.2333 +		{
 89.2334 +			CH->SLOT[s].state     = EG_OFF;
 89.2335 +			CH->SLOT[s].volume    = MAX_ATT_INDEX;
 89.2336 +		}
 89.2337 +	}
 89.2338 +}
 89.2339 +
 89.2340 +/* Create one of virtual YMF262 */
 89.2341 +/* 'clock' is chip clock in Hz  */
 89.2342 +/* 'rate'  is sampling rate  */
 89.2343 +static OPL3 *OPL3Create(running_device *device, int clock, int rate, int type)
 89.2344 +{
 89.2345 +	OPL3 *chip;
 89.2346 +
 89.2347 +	if (OPL3_LockTable(device) == -1) return NULL;
 89.2348 +
 89.2349 +	/* allocate memory block */
 89.2350 +	chip = (OPL3 *)malloc(sizeof(OPL3));//auto_alloc_clear(device->machine, OPL3);
 89.2351 +	memset(chip,0,sizeof(OPL3));
 89.2352 +
 89.2353 +	chip->device = device;
 89.2354 +	chip->type  = type;
 89.2355 +	chip->clock = clock;
 89.2356 +	chip->rate  = rate;
 89.2357 +
 89.2358 +	/* init global tables */
 89.2359 +	OPL3_initalize(chip);
 89.2360 +
 89.2361 +	/* reset chip */
 89.2362 +	OPL3ResetChip(chip);
 89.2363 +	return chip;
 89.2364 +}
 89.2365 +
 89.2366 +/* Destroy one of virtual YMF262 */
 89.2367 +static void OPL3Destroy(OPL3 *chip)
 89.2368 +{
 89.2369 +	OPL3_UnLockTable();
 89.2370 +	free(chip);
 89.2371 +//	auto_free(chip->device->machine, chip);
 89.2372 +}
 89.2373 +
 89.2374 +
 89.2375 +/* Optional handlers */
 89.2376 +
 89.2377 +static void OPL3SetTimerHandler(OPL3 *chip,OPL3_TIMERHANDLER timer_handler,void *param)
 89.2378 +{
 89.2379 +	chip->timer_handler   = timer_handler;
 89.2380 +	chip->TimerParam = param;
 89.2381 +}
 89.2382 +static void OPL3SetIRQHandler(OPL3 *chip,OPL3_IRQHANDLER IRQHandler,void *param)
 89.2383 +{
 89.2384 +	chip->IRQHandler     = IRQHandler;
 89.2385 +	chip->IRQParam = param;
 89.2386 +}
 89.2387 +static void OPL3SetUpdateHandler(OPL3 *chip,OPL3_UPDATEHANDLER UpdateHandler,void *param)
 89.2388 +{
 89.2389 +	chip->UpdateHandler = UpdateHandler;
 89.2390 +	chip->UpdateParam = param;
 89.2391 +}
 89.2392 +
 89.2393 +/* YMF262 I/O interface */
 89.2394 +static int OPL3Write(OPL3 *chip, int a, int v)
 89.2395 +{
 89.2396 +	/* data bus is 8 bits */
 89.2397 +	v &= 0xff;
 89.2398 +	
 89.2399 +//	pclog("OPL3 write %04X %02X\n",a,v);
 89.2400 +
 89.2401 +	switch(a&3)
 89.2402 +	{
 89.2403 +	case 0:	/* address port 0 (register set #1) */
 89.2404 +		chip->address = v;
 89.2405 +	break;
 89.2406 +
 89.2407 +	case 1:	/* data port - ignore A1 */
 89.2408 +	case 3:	/* data port - ignore A1 */
 89.2409 +		if(chip->UpdateHandler) chip->UpdateHandler(chip->UpdateParam,0);
 89.2410 +		OPL3WriteReg(chip,chip->address,v);
 89.2411 +	break;
 89.2412 +
 89.2413 +	case 2:	/* address port 1 (register set #2) */
 89.2414 +
 89.2415 +		/* verified on real YMF262:
 89.2416 +         in OPL3 mode:
 89.2417 +           address line A1 is stored during *address* write and ignored during *data* write.
 89.2418 +
 89.2419 +         in OPL2 mode:
 89.2420 +           register set#2 writes go to register set#1 (ignoring A1)
 89.2421 +           verified on registers from set#2: 0x01, 0x04, 0x20-0xef
 89.2422 +           The only exception is register 0x05.
 89.2423 +        */
 89.2424 +		if( chip->OPL3_mode & 1 )
 89.2425 +		{
 89.2426 +			/* OPL3 mode */
 89.2427 +				chip->address = v | 0x100;
 89.2428 +		}
 89.2429 +		else
 89.2430 +		{
 89.2431 +			/* in OPL2 mode the only accessible in set #2 is register 0x05 */
 89.2432 +			if( v==5 )
 89.2433 +				chip->address = v | 0x100;
 89.2434 +			else
 89.2435 +				chip->address = v;	/* verified range: 0x01, 0x04, 0x20-0xef(set #2 becomes set #1 in opl2 mode) */
 89.2436 +		}
 89.2437 +	break;
 89.2438 +	}
 89.2439 +
 89.2440 +	return chip->status>>7;
 89.2441 +}
 89.2442 +
 89.2443 +static unsigned char OPL3Read(OPL3 *chip,int a)
 89.2444 +{
 89.2445 +	if( a==0 )
 89.2446 +	{
 89.2447 +		/* status port */
 89.2448 +		return chip->status;
 89.2449 +	}
 89.2450 +
 89.2451 +	return 0x00;	/* verified on real YMF262 */
 89.2452 +}
 89.2453 +
 89.2454 +
 89.2455 +
 89.2456 +static int OPL3TimerOver(OPL3 *chip,int c)
 89.2457 +{
 89.2458 +	if( c )
 89.2459 +	{	/* Timer B */
 89.2460 +		OPL3_STATUS_SET(chip,0x20);
 89.2461 +	}
 89.2462 +	else
 89.2463 +	{	/* Timer A */
 89.2464 +		OPL3_STATUS_SET(chip,0x40);
 89.2465 +	}
 89.2466 +	/* reload timer */
 89.2467 +	if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,c,attotime_mul(chip->TimerBase, chip->T[c]));
 89.2468 +	return chip->status>>7;
 89.2469 +}
 89.2470 +
 89.2471 +
 89.2472 +
 89.2473 +
 89.2474 +void * ymf262_init(running_device *device, int clock, int rate)
 89.2475 +{
 89.2476 +	return OPL3Create(device,clock,rate,OPL3_TYPE_YMF262);
 89.2477 +}
 89.2478 +
 89.2479 +void ymf262_shutdown(void *chip)
 89.2480 +{
 89.2481 +	OPL3Destroy((OPL3 *)chip);
 89.2482 +}
 89.2483 +void ymf262_reset_chip(void *chip)
 89.2484 +{
 89.2485 +	OPL3ResetChip((OPL3 *)chip);
 89.2486 +}
 89.2487 +
 89.2488 +int ymf262_write(void *chip, int a, int v)
 89.2489 +{
 89.2490 +	return OPL3Write((OPL3 *)chip, a, v);
 89.2491 +}
 89.2492 +
 89.2493 +unsigned char ymf262_read(void *chip, int a)
 89.2494 +{
 89.2495 +	/* Note on status register: */
 89.2496 +
 89.2497 +	/* YM3526(OPL) and YM3812(OPL2) return bit2 and bit1 in HIGH state */
 89.2498 +
 89.2499 +	/* YMF262(OPL3) always returns bit2 and bit1 in LOW state */
 89.2500 +	/* which can be used to identify the chip */
 89.2501 +
 89.2502 +	/* YMF278(OPL4) returns bit2 in LOW and bit1 in HIGH state ??? info from manual - not verified */
 89.2503 +
 89.2504 +	return OPL3Read((OPL3 *)chip, a&3);
 89.2505 +}
 89.2506 +int ymf262_timer_over(void *chip, int c)
 89.2507 +{
 89.2508 +	return OPL3TimerOver((OPL3 *)chip, c);
 89.2509 +}
 89.2510 +
 89.2511 +void ymf262_set_timer_handler(void *chip, OPL3_TIMERHANDLER timer_handler, void *param)
 89.2512 +{
 89.2513 +	OPL3SetTimerHandler((OPL3 *)chip, timer_handler, param);
 89.2514 +}
 89.2515 +void ymf262_set_irq_handler(void *chip,OPL3_IRQHANDLER IRQHandler,void *param)
 89.2516 +{
 89.2517 +	OPL3SetIRQHandler((OPL3 *)chip, IRQHandler, param);
 89.2518 +}
 89.2519 +void ymf262_set_update_handler(void *chip,OPL3_UPDATEHANDLER UpdateHandler,void *param)
 89.2520 +{
 89.2521 +	OPL3SetUpdateHandler((OPL3 *)chip, UpdateHandler, param);
 89.2522 +}
 89.2523 +
 89.2524 +
 89.2525 +/*
 89.2526 +** Generate samples for one of the YMF262's
 89.2527 +**
 89.2528 +** 'which' is the virtual YMF262 number
 89.2529 +** '**buffers' is table of 4 pointers to the buffers: CH.A, CH.B, CH.C and CH.D
 89.2530 +** 'length' is the number of samples that should be generated
 89.2531 +*/
 89.2532 +void ymf262_update_one(void *_chip, OPL3SAMPLE **buffers, int length)
 89.2533 +{
 89.2534 +	OPL3		*chip  = (OPL3 *)_chip;
 89.2535 +	UINT8		rhythm = chip->rhythm&0x20;
 89.2536 +
 89.2537 +	OPL3SAMPLE	*ch_a = buffers[0];
 89.2538 +	OPL3SAMPLE	*ch_b = buffers[1];
 89.2539 +	OPL3SAMPLE	*ch_c = buffers[2];
 89.2540 +	OPL3SAMPLE	*ch_d = buffers[3];
 89.2541 +
 89.2542 +	int i;
 89.2543 +
 89.2544 +	if( (void *)chip != cur_chip ){
 89.2545 +		cur_chip = (void *)chip;
 89.2546 +		/* rhythm slots */
 89.2547 +		SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1];
 89.2548 +		SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2];
 89.2549 +		SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1];
 89.2550 +		SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2];
 89.2551 +	}
 89.2552 +	for( i=0; i < length ; i++ )
 89.2553 +	{
 89.2554 +		int a,b,c,d;
 89.2555 +
 89.2556 +
 89.2557 +		advance_lfo(chip);
 89.2558 +
 89.2559 +		/* clear channel outputs */
 89.2560 +		memset(chanout, 0, sizeof(signed int) * 18);
 89.2561 +
 89.2562 +#if 1
 89.2563 +	/* register set #1 */
 89.2564 +		chan_calc(&chip->P_CH[0]);			/* extended 4op ch#0 part 1 or 2op ch#0 */
 89.2565 +		if (chip->P_CH[0].extended)
 89.2566 +			chan_calc_ext(&chip->P_CH[3]);	/* extended 4op ch#0 part 2 */
 89.2567 +		else
 89.2568 +			chan_calc(&chip->P_CH[3]);		/* standard 2op ch#3 */
 89.2569 +
 89.2570 +
 89.2571 +		chan_calc(&chip->P_CH[1]);			/* extended 4op ch#1 part 1 or 2op ch#1 */
 89.2572 +		if (chip->P_CH[1].extended)
 89.2573 +			chan_calc_ext(&chip->P_CH[4]);	/* extended 4op ch#1 part 2 */
 89.2574 +		else
 89.2575 +			chan_calc(&chip->P_CH[4]);		/* standard 2op ch#4 */
 89.2576 +
 89.2577 +
 89.2578 +		chan_calc(&chip->P_CH[2]);			/* extended 4op ch#2 part 1 or 2op ch#2 */
 89.2579 +		if (chip->P_CH[2].extended)
 89.2580 +			chan_calc_ext(&chip->P_CH[5]);	/* extended 4op ch#2 part 2 */
 89.2581 +		else
 89.2582 +			chan_calc(&chip->P_CH[5]);		/* standard 2op ch#5 */
 89.2583 +
 89.2584 +
 89.2585 +		if(!rhythm)
 89.2586 +		{
 89.2587 +			chan_calc(&chip->P_CH[6]);
 89.2588 +			chan_calc(&chip->P_CH[7]);
 89.2589 +			chan_calc(&chip->P_CH[8]);
 89.2590 +		}
 89.2591 +		else		/* Rhythm part */
 89.2592 +		{
 89.2593 +			chan_calc_rhythm(&chip->P_CH[0], (chip->noise_rng>>0)&1 );
 89.2594 +		}
 89.2595 +
 89.2596 +	/* register set #2 */
 89.2597 +		chan_calc(&chip->P_CH[ 9]);
 89.2598 +		if (chip->P_CH[9].extended)
 89.2599 +			chan_calc_ext(&chip->P_CH[12]);
 89.2600 +		else
 89.2601 +			chan_calc(&chip->P_CH[12]);
 89.2602 +
 89.2603 +
 89.2604 +		chan_calc(&chip->P_CH[10]);
 89.2605 +		if (chip->P_CH[10].extended)
 89.2606 +			chan_calc_ext(&chip->P_CH[13]);
 89.2607 +		else
 89.2608 +			chan_calc(&chip->P_CH[13]);
 89.2609 +
 89.2610 +
 89.2611 +		chan_calc(&chip->P_CH[11]);
 89.2612 +		if (chip->P_CH[11].extended)
 89.2613 +			chan_calc_ext(&chip->P_CH[14]);
 89.2614 +		else
 89.2615 +			chan_calc(&chip->P_CH[14]);
 89.2616 +
 89.2617 +
 89.2618 +        /* channels 15,16,17 are fixed 2-operator channels only */
 89.2619 +		chan_calc(&chip->P_CH[15]);
 89.2620 +		chan_calc(&chip->P_CH[16]);
 89.2621 +		chan_calc(&chip->P_CH[17]);
 89.2622 +#endif
 89.2623 +
 89.2624 +		/* accumulator register set #1 */
 89.2625 +		a =  chanout[0] & chip->pan[0];
 89.2626 +		b =  chanout[0] & chip->pan[1];
 89.2627 +		c =  chanout[0] & chip->pan[2];
 89.2628 +		d =  chanout[0] & chip->pan[3];
 89.2629 +#if 1
 89.2630 +		a += chanout[1] & chip->pan[4];
 89.2631 +		b += chanout[1] & chip->pan[5];
 89.2632 +		c += chanout[1] & chip->pan[6];
 89.2633 +		d += chanout[1] & chip->pan[7];
 89.2634 +		a += chanout[2] & chip->pan[8];
 89.2635 +		b += chanout[2] & chip->pan[9];
 89.2636 +		c += chanout[2] & chip->pan[10];
 89.2637 +		d += chanout[2] & chip->pan[11];
 89.2638 +
 89.2639 +		a += chanout[3] & chip->pan[12];
 89.2640 +		b += chanout[3] & chip->pan[13];
 89.2641 +		c += chanout[3] & chip->pan[14];
 89.2642 +		d += chanout[3] & chip->pan[15];
 89.2643 +		a += chanout[4] & chip->pan[16];
 89.2644 +		b += chanout[4] & chip->pan[17];
 89.2645 +		c += chanout[4] & chip->pan[18];
 89.2646 +		d += chanout[4] & chip->pan[19];
 89.2647 +		a += chanout[5] & chip->pan[20];
 89.2648 +		b += chanout[5] & chip->pan[21];
 89.2649 +		c += chanout[5] & chip->pan[22];
 89.2650 +		d += chanout[5] & chip->pan[23];
 89.2651 +
 89.2652 +		a += chanout[6] & chip->pan[24];
 89.2653 +		b += chanout[6] & chip->pan[25];
 89.2654 +		c += chanout[6] & chip->pan[26];
 89.2655 +		d += chanout[6] & chip->pan[27];
 89.2656 +		a += chanout[7] & chip->pan[28];
 89.2657 +		b += chanout[7] & chip->pan[29];
 89.2658 +		c += chanout[7] & chip->pan[30];
 89.2659 +		d += chanout[7] & chip->pan[31];
 89.2660 +		a += chanout[8] & chip->pan[32];
 89.2661 +		b += chanout[8] & chip->pan[33];
 89.2662 +		c += chanout[8] & chip->pan[34];
 89.2663 +		d += chanout[8] & chip->pan[35];
 89.2664 +
 89.2665 +		/* accumulator register set #2 */
 89.2666 +		a += chanout[9] & chip->pan[36];
 89.2667 +		b += chanout[9] & chip->pan[37];
 89.2668 +		c += chanout[9] & chip->pan[38];
 89.2669 +		d += chanout[9] & chip->pan[39];
 89.2670 +		a += chanout[10] & chip->pan[40];
 89.2671 +		b += chanout[10] & chip->pan[41];
 89.2672 +		c += chanout[10] & chip->pan[42];
 89.2673 +		d += chanout[10] & chip->pan[43];
 89.2674 +		a += chanout[11] & chip->pan[44];
 89.2675 +		b += chanout[11] & chip->pan[45];
 89.2676 +		c += chanout[11] & chip->pan[46];
 89.2677 +		d += chanout[11] & chip->pan[47];
 89.2678 +
 89.2679 +		a += chanout[12] & chip->pan[48];
 89.2680 +		b += chanout[12] & chip->pan[49];
 89.2681 +		c += chanout[12] & chip->pan[50];
 89.2682 +		d += chanout[12] & chip->pan[51];
 89.2683 +		a += chanout[13] & chip->pan[52];
 89.2684 +		b += chanout[13] & chip->pan[53];
 89.2685 +		c += chanout[13] & chip->pan[54];
 89.2686 +		d += chanout[13] & chip->pan[55];
 89.2687 +		a += chanout[14] & chip->pan[56];
 89.2688 +		b += chanout[14] & chip->pan[57];
 89.2689 +		c += chanout[14] & chip->pan[58];
 89.2690 +		d += chanout[14] & chip->pan[59];
 89.2691 +
 89.2692 +		a += chanout[15] & chip->pan[60];
 89.2693 +		b += chanout[15] & chip->pan[61];
 89.2694 +		c += chanout[15] & chip->pan[62];
 89.2695 +		d += chanout[15] & chip->pan[63];
 89.2696 +		a += chanout[16] & chip->pan[64];
 89.2697 +		b += chanout[16] & chip->pan[65];
 89.2698 +		c += chanout[16] & chip->pan[66];
 89.2699 +		d += chanout[16] & chip->pan[67];
 89.2700 +		a += chanout[17] & chip->pan[68];
 89.2701 +		b += chanout[17] & chip->pan[69];
 89.2702 +		c += chanout[17] & chip->pan[70];
 89.2703 +		d += chanout[17] & chip->pan[71];
 89.2704 +#endif
 89.2705 +		a >>= FINAL_SH;
 89.2706 +		b >>= FINAL_SH;
 89.2707 +		c >>= FINAL_SH;
 89.2708 +		d >>= FINAL_SH;
 89.2709 +
 89.2710 +		/* limit check */
 89.2711 +		a = limit( a , MAXOUT, MINOUT );
 89.2712 +		b = limit( b , MAXOUT, MINOUT );
 89.2713 +		c = limit( c , MAXOUT, MINOUT );
 89.2714 +		d = limit( d , MAXOUT, MINOUT );
 89.2715 +
 89.2716 +		#ifdef SAVE_SAMPLE
 89.2717 +		if (which==0)
 89.2718 +		{
 89.2719 +			SAVE_ALL_CHANNELS
 89.2720 +		}
 89.2721 +		#endif
 89.2722 +
 89.2723 +		/* store to sound buffer */
 89.2724 +		ch_a[i] = a;
 89.2725 +		ch_b[i] = b;
 89.2726 +		ch_c[i] = c;
 89.2727 +		ch_d[i] = d;
 89.2728 +
 89.2729 +		advance(chip);
 89.2730 +	}
 89.2731 +
 89.2732 +}
 89.2733 +
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/src/mame/ymf262.h	Sun Apr 21 14:54:35 2013 +0100
    90.3 @@ -0,0 +1,62 @@
    90.4 +#pragma once
    90.5 +
    90.6 +#ifndef __YMF262_H__
    90.7 +#define __YMF262_H__
    90.8 +
    90.9 +#ifndef STUFF
   90.10 +#define STUFF
   90.11 +typedef int64_t attotime;
   90.12 +#define ATTOTIME_IN_HZ(x) (1000000000/(x))
   90.13 +#define attotime_mul(x,y) ((x)*(y))
   90.14 +#define attotime_to_double(x) ((double)(x)/1000000000.0)
   90.15 +#define attotime_zero 0
   90.16 +
   90.17 +#define running_device void
   90.18 +#define INLINE static
   90.19 +//#define M_PI 3.142
   90.20 +#endif
   90.21 +
   90.22 +/* select number of output bits: 8 or 16 */
   90.23 +#define OPL3_SAMPLE_BITS 16
   90.24 +
   90.25 +/* compiler dependence */
   90.26 +#ifndef __OSDCOMM_H__
   90.27 +#define __OSDCOMM_H__
   90.28 +typedef unsigned char	UINT8;   /* unsigned  8bit */
   90.29 +typedef unsigned short	UINT16;  /* unsigned 16bit */
   90.30 +typedef unsigned int	UINT32;  /* unsigned 32bit */
   90.31 +typedef signed char		INT8;    /* signed  8bit   */
   90.32 +typedef signed short	INT16;   /* signed 16bit   */
   90.33 +typedef signed int		INT32;   /* signed 32bit   */
   90.34 +#endif
   90.35 +
   90.36 +typedef signed short OPL3SAMPLE;
   90.37 +//typedef stream_sample_t OPL3SAMPLE;
   90.38 +/*
   90.39 +#if (OPL3_SAMPLE_BITS==16)
   90.40 +typedef INT16 OPL3SAMPLE;
   90.41 +#endif
   90.42 +#if (OPL3_SAMPLE_BITS==8)
   90.43 +typedef INT8 OPL3SAMPLE;
   90.44 +#endif
   90.45 +*/
   90.46 +
   90.47 +typedef void (*OPL3_TIMERHANDLER)(void *param,int timer,attotime period);
   90.48 +typedef void (*OPL3_IRQHANDLER)(void *param,int irq);
   90.49 +typedef void (*OPL3_UPDATEHANDLER)(void *param,int min_interval_us);
   90.50 +
   90.51 +
   90.52 +void *ymf262_init(running_device *device, int clock, int rate);
   90.53 +void ymf262_shutdown(void *chip);
   90.54 +void ymf262_reset_chip(void *chip);
   90.55 +int  ymf262_write(void *chip, int a, int v);
   90.56 +unsigned char ymf262_read(void *chip, int a);
   90.57 +int  ymf262_timer_over(void *chip, int c);
   90.58 +void ymf262_update_one(void *chip, OPL3SAMPLE **buffers, int length);
   90.59 +
   90.60 +void ymf262_set_timer_handler(void *chip, OPL3_TIMERHANDLER TimerHandler, void *param);
   90.61 +void ymf262_set_irq_handler(void *chip, OPL3_IRQHANDLER IRQHandler, void *param);
   90.62 +void ymf262_set_update_handler(void *chip, OPL3_UPDATEHANDLER UpdateHandler, void *param);
   90.63 +
   90.64 +
   90.65 +#endif /* __YMF262_H__ */
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/src/mcr.c	Sun Apr 21 14:54:35 2013 +0100
    91.3 @@ -0,0 +1,37 @@
    91.4 +/*INTEL 82355 MCR emulation
    91.5 +  This chip was used as part of many 386 chipsets
    91.6 +  It controls memory addressing and shadowing*/
    91.7 +#include "ibm.h"
    91.8 +
    91.9 +int nextreg6;
   91.10 +uint8_t mcr22;
   91.11 +int mcrlock,mcrfirst;
   91.12 +void resetmcr()
   91.13 +{
   91.14 +        mcrlock=0;
   91.15 +        mcrfirst=1;
   91.16 +        shadowbios=0;
   91.17 +}
   91.18 +
   91.19 +void writemcr(uint16_t addr, uint8_t val)
   91.20 +{
   91.21 +        printf("Write MCR %04X %02X %04X:%04X\n",addr,val,CS,pc);
   91.22 +        switch (addr)
   91.23 +        {
   91.24 +                case 0x22:
   91.25 +                if (val==6 && mcr22==6) nextreg6=1;
   91.26 +                else                    nextreg6=0;
   91.27 +//                if ((val&1) && (mcr22&1)) shadowbios=1;
   91.28 +//                if (!(val&1) && !(mcr22&1)) shadowbios=0;
   91.29 +//                if (!mcrfirst) shadowbios=val&1;
   91.30 +//                mcrfirst=0;
   91.31 +//                dumpregs();
   91.32 +//                exit(-1);
   91.33 +                break;
   91.34 +                case 0x23:
   91.35 +                if (nextreg6) shadowbios=!val;
   91.36 +                break;
   91.37 +        }
   91.38 +        mcr22=val;
   91.39 +}
   91.40 +
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/src/mem.c	Sun Apr 21 14:54:35 2013 +0100
    92.3 @@ -0,0 +1,1358 @@
    92.4 +/*MESS ROM notes :
    92.5 +        
    92.6 +        - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM)
    92.7 +        - pc2386 video BIOS is underdumped (16k instead of 24k)
    92.8 +        - c386sx16 BIOS fails checksum
    92.9 +*/
   92.10 +
   92.11 +#include <stdlib.h>
   92.12 +#include <string.h>
   92.13 +#include "ibm.h"
   92.14 +#include "mem.h"
   92.15 +#include "video.h"
   92.16 +#include "x86.h"
   92.17 +#include "cpu.h"
   92.18 +
   92.19 +static uint8_t  (*_mem_read_b[0x20000])(uint32_t addr);
   92.20 +static uint16_t (*_mem_read_w[0x20000])(uint32_t addr);
   92.21 +static uint32_t (*_mem_read_l[0x20000])(uint32_t addr);
   92.22 +static void    (*_mem_write_b[0x20000])(uint32_t addr, uint8_t  val);
   92.23 +static void    (*_mem_write_w[0x20000])(uint32_t addr, uint16_t val);
   92.24 +static void    (*_mem_write_l[0x20000])(uint32_t addr, uint32_t val);
   92.25 +
   92.26 +int shadowbios,shadowbios_write;
   92.27 +
   92.28 +uint32_t oldpc;
   92.29 +extern uint8_t opcode2;
   92.30 +unsigned char isram[0x10000];
   92.31 +extern int ins;
   92.32 +extern int timetolive;
   92.33 +
   92.34 +int mem_size;
   92.35 +int cache=4;
   92.36 +uint32_t biosmask;
   92.37 +int readlnum=0,writelnum=0;
   92.38 +int cachesize=256;
   92.39 +
   92.40 +uint8_t *ram,*rom,*vram,*vrom;
   92.41 +uint8_t romext[32768];
   92.42 +
   92.43 +FILE *romfopen(char *fn, char *mode)
   92.44 +{
   92.45 +        char s[512];
   92.46 +        pclog("romfopen %s\n", fn);
   92.47 +        strcpy(s,pcempath);
   92.48 +        pclog("s = %s\n", s);
   92.49 +        put_backslash(s);
   92.50 +        pclog("s = %s\n", s);
   92.51 +        pclog("strcat %s %s\n", s, fn);
   92.52 +        strcat(s,fn);
   92.53 +        pclog("s = %s\n", s);
   92.54 +        return fopen(s,mode);
   92.55 +}
   92.56 +
   92.57 +static void mem_load_xtide_bios()
   92.58 +{
   92.59 +        FILE *f;
   92.60 +        f=romfopen("roms/ide_xt.bin","rb");
   92.61 +
   92.62 +//        is486=0;
   92.63 +        if (f)
   92.64 +        {
   92.65 +                fread(romext,16384,1,f);
   92.66 +                fclose(f);
   92.67 +        }
   92.68 +}
   92.69 +        
   92.70 +static void mem_load_atide_bios()
   92.71 +{
   92.72 +        FILE *f;
   92.73 +        f=romfopen("roms/ide_at.bin","rb");
   92.74 +
   92.75 +//        is486=0;
   92.76 +        if (f)
   92.77 +        {
   92.78 +                fread(romext,16384,1,f);
   92.79 +                fclose(f);
   92.80 +        }
   92.81 +}
   92.82 +        
   92.83 +int loadbios()
   92.84 +{
   92.85 +        FILE *f=NULL,*ff=NULL;
   92.86 +        int c;
   92.87 +        
   92.88 +        loadfont("mda.rom", 0);
   92.89 +        
   92.90 +        memset(vrom,0x63,0x8000);
   92.91 +//        printf("Loadrom - VGA %i\n",VGA);
   92.92 +        if (VID_EGA)
   92.93 +        {
   92.94 +                f=romfopen("roms/ibm_6277356_ega_card_u44_27128.bin","rb");
   92.95 +                if (f)
   92.96 +                {
   92.97 +                        pclog("Read EGA ROM!\n");
   92.98 +                        fread(vrom,16384,1,f);
   92.99 +                        if (vrom[0x3FFE]==0xAA && vrom[0x3FFF]==0x55)
  92.100 +                        {
  92.101 +                                pclog("Read EGA ROM in reverse\n");
  92.102 +                                fseek(f,0,SEEK_SET);
  92.103 +                                for (c=0x3FFF;c>=0;c--)
  92.104 +                                    vrom[c]=getc(f);
  92.105 +                        }
  92.106 +                        fclose(f);
  92.107 +                }
  92.108 +        }
  92.109 +        if (VGA)
  92.110 +        {
  92.111 +                f=romfopen("roms/trident.bin","rb");
  92.112 +                if (f)
  92.113 +                {
  92.114 +                        fread(vrom,32768,1,f);
  92.115 +                        fclose(f);
  92.116 +                }
  92.117 +        }
  92.118 +        if (ET4000)
  92.119 +        {
  92.120 +                f=romfopen("roms/et4000.bin","rb");
  92.121 +                if (f)
  92.122 +                {
  92.123 +                        fread(vrom,32768,1,f);
  92.124 +                        fclose(f);
  92.125 +                }
  92.126 +        }
  92.127 +        if (ET4000W32)
  92.128 +        {
  92.129 +                f=romfopen("roms/et4000w32.bin","rb");
  92.130 +                if (f)
  92.131 +                {
  92.132 +                        fread(vrom,32768,1,f);
  92.133 +                        fclose(f);
  92.134 +                }
  92.135 +        }
  92.136 +        if (gfxcard == GFX_BAHAMAS64)
  92.137 +        {
  92.138 +                f=romfopen("roms/bahamas64.bin","rb");
  92.139 +                if (f)
  92.140 +                {
  92.141 +                        fread(vrom,32768,1,f);
  92.142 +                        fclose(f);
  92.143 +                }
  92.144 +        }
  92.145 +        if (gfxcard == GFX_N9_9FX)
  92.146 +        {
  92.147 +                f=romfopen("roms/s3_764.bin","rb");
  92.148 +                if (f)
  92.149 +                {
  92.150 +                        fread(vrom,32768,1,f);
  92.151 +                        fclose(f);
  92.152 +                }
  92.153 +        }
  92.154 +        if (gfxcard == GFX_STEALTH64)
  92.155 +        {
  92.156 +                f=romfopen("roms/TRIO64 (Ver. 1.5-07) [VGA] (S3 Incorporated).bin","rb");
  92.157 +                if (f)
  92.158 +                {
  92.159 +                        fread(vrom,32768,1,f);
  92.160 +                        fclose(f);
  92.161 +                }
  92.162 +        }
  92.163 +
  92.164 +        memset(romext,0x63,0x8000);
  92.165 +        
  92.166 +        biosmask = 0xffff;
  92.167 +        
  92.168 +        pclog("Starting with romset %i\n", romset);
  92.169 +        
  92.170 +        switch (romset)
  92.171 +        {
  92.172 +                case ROM_PC1512:
  92.173 +                f=romfopen("roms/pc1512/40043.v1","rb");
  92.174 +                ff=romfopen("roms/pc1512/40044.v1","rb");
  92.175 +                if (!f || !ff) break;
  92.176 +                for (c=0xC000;c<0x10000;c+=2)
  92.177 +                {
  92.178 +                        rom[c]=getc(f);
  92.179 +                        rom[c+1]=getc(ff);
  92.180 +                }
  92.181 +                fclose(ff);
  92.182 +                fclose(f);
  92.183 +                memset(vrom,0x63,0x8000);
  92.184 +                mem_load_xtide_bios();
  92.185 +                loadfont("roms/pc1512/40078.ic127", 2);
  92.186 +                return 1;
  92.187 +                case ROM_PC1640:
  92.188 +                f=romfopen("roms/pc1640/40044.v3","rb");
  92.189 +                ff=romfopen("roms/pc1640/40043.v3","rb");
  92.190 +                if (!f || !ff) break;
  92.191 +                for (c=0xC000;c<0x10000;c+=2)
  92.192 +                {
  92.193 +                        rom[c]=getc(f);
  92.194 +                        rom[c+1]=getc(ff);
  92.195 +                }
  92.196 +                fclose(ff);
  92.197 +                fclose(f);
  92.198 +                f=romfopen("roms/pc1640/40100","rb");
  92.199 +                if (!f) break;
  92.200 +                fread(vrom,0x8000,1,f);
  92.201 +                fclose(f);
  92.202 +                mem_load_xtide_bios();
  92.203 +                return 1;
  92.204 +                case ROM_PC200:
  92.205 +                f=romfopen("roms/pc200/pc20v2.1","rb");
  92.206 +                ff=romfopen("roms/pc200/pc20v2.0","rb");
  92.207 +                if (!f || !ff) break;
  92.208 +                for (c=0xC000;c<0x10000;c+=2)
  92.209 +                {
  92.210 +                        rom[c]=getc(f);
  92.211 +                        rom[c+1]=getc(ff);
  92.212 +                }
  92.213 +                fclose(ff);
  92.214 +                fclose(f);
  92.215 +                memset(vrom,0x63,0x8000);
  92.216 +                mem_load_xtide_bios();
  92.217 +                loadfont("roms/pc200/40109.bin", 1);
  92.218 +                return 1;
  92.219 +                case ROM_TANDY:
  92.220 +                f=romfopen("roms/tandy/tandy1t1.020","rb");
  92.221 +                if (!f) break;
  92.222 +                fread(rom,65536,1,f);
  92.223 +                fclose(f);
  92.224 +                memset(vrom,0x63,0x8000);
  92.225 +                mem_load_xtide_bios();
  92.226 +                return 1;
  92.227 +/*                case ROM_IBMPCJR:
  92.228 +                f=fopen("pcjr/bios.rom","rb");
  92.229 +                fread(rom+0xE000,8192,1,f);
  92.230 +                fclose(f);
  92.231 +                f=fopen("pcjr/basic.rom","rb");
  92.232 +                fread(rom+0x6000,32768,1,f);
  92.233 +                fclose(f);
  92.234 +                break;*/
  92.235 +                case ROM_IBMXT:
  92.236 +                f=romfopen("roms/ibmxt/xt.rom","rb");
  92.237 +                if (!f)
  92.238 +                {
  92.239 +                        f=romfopen("roms/ibmxt/xt050986.0","rb");
  92.240 +                        ff=romfopen("roms/ibmxt/xt050986.1","rb");
  92.241 +                        if (!f || !ff) break;
  92.242 +                        for (c=0x0000;c<0x10000;c+=2)
  92.243 +                        {
  92.244 +                                rom[c]=getc(f);
  92.245 +                                rom[c+1]=getc(ff);
  92.246 +                        }
  92.247 +                        fclose(ff);
  92.248 +                        fclose(f);
  92.249 +                        mem_load_xtide_bios();
  92.250 +                        return 1;
  92.251 +                }
  92.252 +                else
  92.253 +                {
  92.254 +                        fread(rom,65536,1,f);
  92.255 +                        fclose(f);
  92.256 +                        mem_load_xtide_bios();
  92.257 +                        return 1;
  92.258 +                }
  92.259 +                break;
  92.260 +                case ROM_GENXT:
  92.261 +                f=romfopen("roms/genxt/pcxt.rom","rb");
  92.262 +                if (!f) break;
  92.263 +                fread(rom+0xE000,8192,1,f);
  92.264 +                fclose(f);
  92.265 +                mem_load_xtide_bios();
  92.266 +                return 1;
  92.267 +                case ROM_DTKXT:
  92.268 +                f=romfopen("roms/dtk/DTK_ERSO_2.42_2764.bin","rb");
  92.269 +                if (!f) break;
  92.270 +                fread(rom+0xE000,8192,1,f);
  92.271 +                fclose(f);
  92.272 +                mem_load_xtide_bios();
  92.273 +                return 1;
  92.274 +                case ROM_OLIM24:
  92.275 +                f  = romfopen("roms/olivetti_m24/olivetti_m24_version_1.43_low.bin" ,"rb");
  92.276 +                ff = romfopen("roms/olivetti_m24/olivetti_m24_version_1.43_high.bin","rb");
  92.277 +                if (!f || !ff) break;
  92.278 +                for (c = 0x0000; c < 0x4000; c += 2)
  92.279 +                {
  92.280 +                        rom[c + 0xc000] = getc(f);
  92.281 +                        rom[c + 0xc001] = getc(ff);
  92.282 +                }
  92.283 +                fclose(ff);
  92.284 +                fclose(f);
  92.285 +                mem_load_xtide_bios();
  92.286 +                return 1;
  92.287 +                        
  92.288 +                case ROM_PC2086:
  92.289 +                f  = romfopen("roms/pc2086/40179.ic129" ,"rb");
  92.290 +                ff = romfopen("roms/pc2086/40180.ic132","rb");
  92.291 +                if (!f || !ff) break;
  92.292 +                pclog("Loading BIOS\n");
  92.293 +                for (c = 0x0000; c < 0x4000; c += 2)
  92.294 +                {
  92.295 +                        rom[c + 0x0000] = getc(f);
  92.296 +                        rom[c + 0x0001] = getc(ff);
  92.297 +                }
  92.298 +                pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]);
  92.299 +                fclose(ff);
  92.300 +                fclose(f);
  92.301 +                f = romfopen("roms/pc2086/40186.ic171", "rb");
  92.302 +                if (!f) break;
  92.303 +                pclog("Loading VBIOS\n");
  92.304 +                fread(vrom, 32768, 1, f);
  92.305 +                fclose(f);
  92.306 +                mem_load_xtide_bios();
  92.307 +                pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]);
  92.308 +                biosmask = 0x3fff;
  92.309 +                return 1;
  92.310 +
  92.311 +                case ROM_PC3086:
  92.312 +                f  = romfopen("roms/pc3086/fc00.bin" ,"rb");
  92.313 +                if (!f) break;
  92.314 +                fread(rom, 0x4000, 1, f);
  92.315 +                fclose(f);
  92.316 +                f = romfopen("roms/pc3086/c000.bin", "rb");
  92.317 +                if (!f) break;
  92.318 +                pclog("Loading VBIOS\n");
  92.319 +                fread(vrom, 32768, 1, f);
  92.320 +                fclose(f);
  92.321 +                mem_load_xtide_bios();
  92.322 +                pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]);
  92.323 +                biosmask = 0x3fff;                
  92.324 +                return 1;
  92.325 +
  92.326 +                case ROM_IBMAT:
  92.327 +/*                f=romfopen("roms/AMIC206.BIN","rb");
  92.328 +                if (!f) break;
  92.329 +                fread(rom,65536,1,f);
  92.330 +                fclose(f);
  92.331 +                return 1;*/
  92.332 +                case ROM_IBMAT386:
  92.333 +                f=romfopen("roms/ibmat/at111585.0","rb");
  92.334 +                ff=romfopen("roms/ibmat/at111585.1","rb");
  92.335 +                if (!f || !ff) break;
  92.336 +                for (c=0x0000;c<0x10000;c+=2)
  92.337 +                {
  92.338 +                        rom[c]=getc(f);
  92.339 +                        rom[c+1]=getc(ff);
  92.340 +                }
  92.341 +                fclose(ff);
  92.342 +                fclose(f);
  92.343 +                mem_load_atide_bios();
  92.344 +                return 1;
  92.345 +                case ROM_CMDPC30:
  92.346 +                f  = romfopen("roms/cmdpc30/commodore pc 30 iii even.bin", "rb");
  92.347 +                ff = romfopen("roms/cmdpc30/commodore pc 30 iii odd.bin",  "rb");
  92.348 +                if (!f || !ff) break;
  92.349 +                for (c = 0x0000; c < 0x8000; c += 2)
  92.350 +                {
  92.351 +                        rom[c]     = getc(f);
  92.352 +                        rom[c + 1] = getc(ff);
  92.353 +                }
  92.354 +                fclose(ff);
  92.355 +                fclose(f);
  92.356 +                biosmask = 0x7fff;
  92.357 +                mem_load_atide_bios();
  92.358 +                return 1;
  92.359 +                case ROM_DELL200:
  92.360 +                f=romfopen("roms/dells200/dell0.bin","rb");
  92.361 +                ff=romfopen("roms/dells200/dell1.bin","rb");
  92.362 +                if (!f || !ff) break;
  92.363 +                for (c=0x0000;c<0x10000;c+=2)
  92.364 +                {
  92.365 +                        rom[c]=getc(f);
  92.366 +                        rom[c+1]=getc(ff);
  92.367 +                }
  92.368 +                fclose(ff);
  92.369 +                fclose(f);
  92.370 +                return 1;
  92.371 +/*                case ROM_IBMAT386:
  92.372 +                f=romfopen("roms/at386/at386.bin","rb");
  92.373 +                if (!f) break;
  92.374 +                fread(rom,65536,1,f);
  92.375 +                fclose(f);
  92.376 +                return 1;*/
  92.377 +                case ROM_AMI386: /*This uses the OPTi 82C495 chipset*/
  92.378 +//                f=romfopen("roms/at386/at386.bin","rb");
  92.379 +                f=romfopen("roms/ami386/ami386.bin","rb");
  92.380 +                if (!f) break;
  92.381 +                fread(rom,65536,1,f);
  92.382 +                fclose(f);
  92.383 +                return 1;
  92.384 +
  92.385 +
  92.386 +                case ROM_ACER386:
  92.387 +                f=romfopen("roms/acer386/acer386.bin","rb");
  92.388 +                if (!f) break;
  92.389 +                fread(rom,65536,1,f);
  92.390 +                fclose(f);
  92.391 +                rom[0xB0]=0xB0-0x51;
  92.392 +                rom[0x40d4]=0x51; /*PUSH CX*/
  92.393 +                f=romfopen("roms/acer386/oti067.bin","rb");
  92.394 +                if (!f) break;
  92.395 +                fread(vrom,0x8000,1,f);
  92.396 +                fclose(f);
  92.397 +                vrom[0x5D]=0x74;
  92.398 +                return 1;
  92.399 +
  92.400 +                case ROM_AMI286:
  92.401 +                f=romfopen("roms/ami286/amic206.bin","rb");
  92.402 +                if (!f) break;
  92.403 +                fread(rom,65536,1,f);
  92.404 +                fclose(f);
  92.405 +//                memset(romext,0x63,0x8000);
  92.406 +                return 1;
  92.407 +
  92.408 +                case ROM_EUROPC:
  92.409 +//                return 0;
  92.410 +                f=romfopen("roms/europc/50145","rb");
  92.411 +                if (!f) break;
  92.412 +                fread(rom+0x8000,32768,1,f);
  92.413 +                fclose(f);
  92.414 +//                memset(romext,0x63,0x8000);
  92.415 +                return 1;
  92.416 +
  92.417 +                case ROM_IBMPC:
  92.418 +                f=romfopen("roms/ibmpc/pc102782.bin","rb");
  92.419 +                if (!f) break;
  92.420 +//                f=fopen("pc081682.bin","rb");
  92.421 +                fread(rom+0xE000,8192,1,f);
  92.422 +                fclose(f);
  92.423 +                f=romfopen("roms/ibmpc/basicc11.f6","rb");
  92.424 +                if (!f) return 1; /*I don't really care if BASIC is there or not*/
  92.425 +                fread(rom+0x6000,8192,1,f);
  92.426 +                fclose(f);
  92.427 +                f=romfopen("roms/ibmpc/basicc11.f8","rb");
  92.428 +                if (!f) break; /*But if some of it is there, then all of it must be*/
  92.429 +                fread(rom+0x8000,8192,1,f);
  92.430 +                fclose(f);
  92.431 +                f=romfopen("roms/ibmpc/basicc11.fa","rb");
  92.432 +                if (!f) break;
  92.433 +                fread(rom+0xA000,8192,1,f);
  92.434 +                fclose(f);
  92.435 +                f=romfopen("roms/ibmpc/basicc11.fc","rb");
  92.436 +                if (!f) break;
  92.437 +                fread(rom+0xC000,8192,1,f);
  92.438 +                fclose(f);
  92.439 +                mem_load_xtide_bios();
  92.440 +                return 1;
  92.441 +
  92.442 +                case ROM_MEGAPC:
  92.443 +                        pclog("Loading MegaPC\n");
  92.444 +                f  = romfopen("roms/megapc/41651-bios lo.u18",  "rb");
  92.445 +                ff = romfopen("roms/megapc/211253-bios hi.u19", "rb");
  92.446 +                if (!f || !ff) break;
  92.447 +                for (c = 0x0000; c < 0x8000; c+=2)
  92.448 +                {
  92.449 +                        vrom[c]=getc(f);
  92.450 +                        vrom[c+1]=getc(ff);
  92.451 +                }
  92.452 +                fseek(f,  0x8000, SEEK_SET);
  92.453 +                fseek(ff, 0x8000, SEEK_SET);                
  92.454 +                for (c = 0x0000; c < 0x10000; c+=2)
  92.455 +                {
  92.456 +                        rom[c]=getc(f);
  92.457 +                        rom[c+1]=getc(ff);
  92.458 +                }
  92.459 +                fclose(ff);
  92.460 +                fclose(f);
  92.461 +                return 1;
  92.462 +                        
  92.463 +                case ROM_AMI486:
  92.464 +                f=romfopen("roms/ami486/ami486.BIN","rb");
  92.465 +                if (!f) break;
  92.466 +                fread(rom,65536,1,f);
  92.467 +                fclose(f);
  92.468 +                //is486=1;
  92.469 +                return 1;
  92.470 +                
  92.471 +                case ROM_WIN486:
  92.472 +//                f=romfopen("roms/win486/win486.bin","rb");
  92.473 +                f=romfopen("roms/win486/ALI1429G.AMW","rb");
  92.474 +                
  92.475 +                if (!f) break;
  92.476 +                fread(rom,65536,1,f);
  92.477 +                fclose(f);
  92.478 +                //is486=1;
  92.479 +                return 1;
  92.480 +
  92.481 +                case ROM_PCI486:
  92.482 +                f=romfopen("roms/hot-433/hot-433.ami","rb");               
  92.483 +                if (!f) break;
  92.484 +                fread(rom,           0x20000, 1, f);                
  92.485 +                fclose(f);
  92.486 +                biosmask = 0x1ffff;
  92.487 +                //is486=1;
  92.488 +                return 1;
  92.489 +
  92.490 +        }
  92.491 +        printf("Failed to load ROM!\n");
  92.492 +        if (f) fclose(f);
  92.493 +        if (ff) fclose(ff);
  92.494 +        return 0;
  92.495 +}
  92.496 +
  92.497 +
  92.498 +
  92.499 +uint32_t mmucache[0x100000];
  92.500 +int mmucaches[64];
  92.501 +int mmunext=0;
  92.502 +int abrt=0;
  92.503 +
  92.504 +void initmmucache()
  92.505 +{
  92.506 +        int c;
  92.507 +//        if (output) pclog("initmmucache\n");
  92.508 +        memset(mmucache,0xFF,sizeof(mmucache));
  92.509 +        for (c=0;c<64;c++) mmucaches[c]=0xFFFFFFFF;
  92.510 +        mmunext=0;
  92.511 +}
  92.512 +
  92.513 +void resetreadlookup()
  92.514 +{
  92.515 +        int c;
  92.516 +//        /*if (output) */pclog("resetreadlookup\n");
  92.517 +        memset(readlookup2,0xFF,1024*1024*4);
  92.518 +        for (c=0;c<256;c++) readlookup[c]=0xFFFFFFFF;
  92.519 +        readlnext=0;
  92.520 +        memset(writelookup2,0xFF,1024*1024*4);
  92.521 +        for (c=0;c<256;c++) writelookup[c]=0xFFFFFFFF;
  92.522 +        writelnext=0;
  92.523 +        pccache=0xFFFFFFFF;
  92.524 +//        readlnum=writelnum=0;
  92.525 +
  92.526 +}
  92.527 +
  92.528 +int mmuflush=0;
  92.529 +int mmu_perm=4;
  92.530 +
  92.531 +void flushmmucache()
  92.532 +{
  92.533 +        int c;
  92.534 +//        /*if (output) */pclog("flushmmucache\n");
  92.535 +/*        for (c=0;c<16;c++)
  92.536 +        {
  92.537 +                if ( readlookup2[0xE0+c]!=0xFFFFFFFF) pclog("RL2 %02X = %08X\n",0xE0+c, readlookup2[0xE0+c]);
  92.538 +                if (writelookup2[0xE0+c]!=0xFFFFFFFF) pclog("WL2 %02X = %08X\n",0xE0+c,writelookup2[0xE0+c]);
  92.539 +        }*/
  92.540 +        for (c=0;c<256;c++)
  92.541 +        {
  92.542 +                if (readlookup[c]!=0xFFFFFFFF)
  92.543 +                {
  92.544 +                        readlookup2[readlookup[c]]=0xFFFFFFFF;
  92.545 +                        readlookup[c]=0xFFFFFFFF;
  92.546 +                }
  92.547 +                if (writelookup[c]!=0xFFFFFFFF)
  92.548 +                {
  92.549 +                        writelookup2[writelookup[c]]=0xFFFFFFFF;
  92.550 +                        writelookup[c]=0xFFFFFFFF;
  92.551 +                }
  92.552 +        }
  92.553 +        mmuflush++;
  92.554 +//        readlnum=writelnum=0;
  92.555 +        pccache=(uint32_t)0xFFFFFFFF;
  92.556 +        pccache2=(uint8_t *)0xFFFFFFFF;
  92.557 +        
  92.558 +//        memset(readlookup,0xFF,sizeof(readlookup));
  92.559 +//        memset(readlookup2,0xFF,1024*1024*4);
  92.560 +//        memset(writelookup,0xFF,sizeof(writelookup));
  92.561 +//        memset(writelookup2,0xFF,1024*1024*4);
  92.562 +/*        if (!(cr0>>31)) return;*/
  92.563 +        for (c=0;c<64;c++)
  92.564 +        {
  92.565 +                if (mmucaches[c]!=0xFFFFFFFF)
  92.566 +                {
  92.567 +                        mmucache[mmucaches[c]]=0xFFFFFFFF;
  92.568 +                        mmucaches[c]=0xFFFFFFFF;
  92.569 +                }
  92.570 +        }
  92.571 +//        pclog("Flush MMU cache\n");
  92.572 +
  92.573 +/*        for (c = 0; c < 1024*1024; c++)
  92.574 +        {
  92.575 +                if (readlookup2[c] != 0xFFFFFFFF)
  92.576 +                {
  92.577 +                        pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
  92.578 +                        dumpregs();
  92.579 +                        exit(-1);
  92.580 +                }
  92.581 +                if (writelookup2[c] != 0xFFFFFFFF)
  92.582 +                {
  92.583 +                        pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
  92.584 +                        dumpregs();
  92.585 +                        exit(-1);
  92.586 +                }
  92.587 +        }*/
  92.588 +}
  92.589 +
  92.590 +void flushmmucache_nopc()
  92.591 +{
  92.592 +        int c;
  92.593 +        for (c=0;c<256;c++)
  92.594 +        {
  92.595 +                if (readlookup[c]!=0xFFFFFFFF)
  92.596 +                {
  92.597 +                        readlookup2[readlookup[c]]=0xFFFFFFFF;
  92.598 +                        readlookup[c]=0xFFFFFFFF;
  92.599 +                }
  92.600 +                if (writelookup[c]!=0xFFFFFFFF)
  92.601 +                {
  92.602 +                        writelookup2[writelookup[c]]=0xFFFFFFFF;
  92.603 +                        writelookup[c]=0xFFFFFFFF;
  92.604 +                }
  92.605 +        }
  92.606 +        mmuflush++;
  92.607 +        for (c=0;c<64;c++)
  92.608 +        {
  92.609 +                if (mmucaches[c]!=0xFFFFFFFF)
  92.610 +                {
  92.611 +                        mmucache[mmucaches[c]]=0xFFFFFFFF;
  92.612 +                        mmucaches[c]=0xFFFFFFFF;
  92.613 +                }
  92.614 +        }
  92.615 +}
  92.616 +
  92.617 +void flushmmucache_cr3()
  92.618 +{
  92.619 +        int c;
  92.620 +//        /*if (output) */pclog("flushmmucache_cr3\n");
  92.621 +        for (c=0;c<256;c++)
  92.622 +        {
  92.623 +                if (readlookup[c]!=0xFFFFFFFF)// && !readlookupp[c])
  92.624 +                {
  92.625 +                        readlookup2[readlookup[c]]=0xFFFFFFFF;
  92.626 +                        readlookup[c]=0xFFFFFFFF;
  92.627 +                }
  92.628 +                if (writelookup[c]!=0xFFFFFFFF)// && !writelookupp[c])
  92.629 +                {
  92.630 +                        writelookup2[writelookup[c]]=0xFFFFFFFF;
  92.631 +                        writelookup[c]=0xFFFFFFFF;
  92.632 +                }
  92.633 +        }
  92.634 +        for (c=0;c<64;c++)
  92.635 +        {
  92.636 +                if (mmucaches[c]!=0xFFFFFFFF)
  92.637 +                {
  92.638 +                        mmucache[mmucaches[c]]=0xFFFFFFFF;
  92.639 +                        mmucaches[c]=0xFFFFFFFF;
  92.640 +                }
  92.641 +        }
  92.642 +
  92.643 +/*        for (c = 0; c < 1024*1024; c++)
  92.644 +        {
  92.645 +                if (readlookup2[c] != 0xFFFFFFFF)
  92.646 +                {
  92.647 +                        pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
  92.648 +                        dumpregs();
  92.649 +                        exit(-1);
  92.650 +                }
  92.651 +                if (writelookup2[c] != 0xFFFFFFFF)
  92.652 +                {
  92.653 +                        pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
  92.654 +                        dumpregs();
  92.655 +                        exit(-1);
  92.656 +                }
  92.657 +        }*/
  92.658 +}
  92.659 +
  92.660 +extern int output;
  92.661 +#define mmutranslate(addr,rw) mmutranslatereal(addr,rw)
  92.662 +//#define mmutranslate(addr,rw) ((mmucache[addr>>12]!=0xFFFFFFFF)?(mmucache[addr>>12]+(addr&0xFFF)):mmutranslatereal(addr,rw))
  92.663 +int pctrans=0;
  92.664 +
  92.665 +extern uint32_t testr[9];
  92.666 +
  92.667 +uint32_t mmutranslatereal(uint32_t addr, int rw)
  92.668 +{
  92.669 +        int mmuout=0;
  92.670 +        uint32_t addr2;
  92.671 +        uint32_t temp,temp2,temp3;
  92.672 +                if (abrt) return -1;
  92.673 +/*                if ((addr&~0xFFFFF)==0x77f00000) pclog("Do translate %08X %i  %08X  %08X\n",addr,rw,EAX,pc);
  92.674 +                if (addr==0x77f61000) output = 3;
  92.675 +                if (addr==0x77f62000) { dumpregs(); exit(-1); }
  92.676 +                if (addr==0x77f9a000) { dumpregs(); exit(-1); }*/
  92.677 +        addr2=(cr3+((addr>>20)&0xFFC));
  92.678 +        temp=temp2=((uint32_t *)ram)[addr2>>2];
  92.679 +//        pclog("Do translate %08X %i %08X\n", addr, rw, temp);
  92.680 +        if (!(temp&1))// || (CPL==3 && !(temp&4) && !cpl_override) || (rw && !(temp&2) && (CPL==3 || cr0&WP_FLAG)))
  92.681 +        {
  92.682 +//                if (/*output==3 && */!nopageerrors) pclog("Section not present! %08X  %08X  %02X  %04X:%08X  %i %i\n",addr,temp,opcode,CS,pc,CPL,rw);
  92.683 +
  92.684 +                cr2=addr;
  92.685 +                temp&=1;
  92.686 +                if (CPL==3) temp|=4;
  92.687 +                if (rw) temp|=2;
  92.688 +                abrt = ABRT_PF;
  92.689 +                abrt_error = temp;
  92.690 +/*                if (addr == 0x70046D)
  92.691 +                {
  92.692 +                        dumpregs();
  92.693 +                        exit(-1);
  92.694 +                }*/
  92.695 +                return -1;
  92.696 +        }
  92.697 +        temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2];
  92.698 +        temp3=temp&temp2;
  92.699 +//        pclog("Do translate %08X %08X\n", temp, temp3);
  92.700 +        if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG)))
  92.701 +        {
  92.702 +//                if (!nopageerrors) pclog("Page not present!  %08X   %08X   %02X %02X  %04X:%08X  %04X:%08X %i  %i %i\n",addr,temp,opcode,opcode2,CS,pc,SS,ESP,ins,CPL,rw);
  92.703 +//                if (addr == 0x815F6E90) output = 3;
  92.704 +/*                if (addr == 0x10ADE020) output = 3;
  92.705 +                if (addr == 0x10000008)
  92.706 +                {
  92.707 +                        dumpregs();
  92.708 +                        exit(-1);
  92.709 +                }*/
  92.710 +
  92.711 +                cr2=addr;
  92.712 +                temp&=1;
  92.713 +                if (CPL==3) temp|=4;
  92.714 +                if (rw) temp|=2;
  92.715 +                abrt = ABRT_PF;
  92.716 +                abrt_error = temp;
  92.717 +//                pclog("%04X\n",abrt);
  92.718 +                return -1;
  92.719 +        }
  92.720 +        mmu_perm=temp&4;
  92.721 +        ((uint32_t *)ram)[addr2>>2]|=0x20;
  92.722 +        ((uint32_t *)ram)[((temp2&~0xFFF)+((addr>>10)&0xFFC))>>2]|=(rw?0x60:0x20);
  92.723 +//        /*if (output) */pclog("Translate %08X %08X %08X  %08X:%08X  %08X\n",addr,(temp&~0xFFF)+(addr&0xFFF),temp,cs,pc,EDI);
  92.724 +
  92.725 +        return (temp&~0xFFF)+(addr&0xFFF);
  92.726 +}
  92.727 +
  92.728 +void mmu_invalidate(uint32_t addr)
  92.729 +{
  92.730 +//        readlookup2[addr >> 12] = writelookup2[addr >> 12] = 0xFFFFFFFF;
  92.731 +        flushmmucache_cr3();
  92.732 +}
  92.733 +
  92.734 +int memspeed[11]={256,320,384,512,640,768,1024,1152,1280,1536,1920};
  92.735 +int memwaitstate;
  92.736 +
  92.737 +static int cachelookup[256];
  92.738 +static uint8_t *cachelookup2;
  92.739 +static int cachelnext;
  92.740 +
  92.741 +void addreadlookup(uint32_t virt, uint32_t phys)
  92.742 +{
  92.743 +//        return;
  92.744 +//        printf("Addreadlookup %08X %08X %08X %08X %08X %08X %02X %08X\n",virt,phys,cs,ds,es,ss,opcode,pc);
  92.745 +        if (readlookup2[virt>>12]!=0xFFFFFFFF) 
  92.746 +        {
  92.747 +/*                if (readlookup2[virt>>12] != phys&~0xfff)
  92.748 +                {
  92.749 +                        pclog("addreadlookup mismatch - %05X000 %05X000\n", readlookup[readlnext], virt >> 12);
  92.750 +                        dumpregs();
  92.751 +                        exit(-1);
  92.752 +                }*/
  92.753 +                return;
  92.754 +        }
  92.755 +        
  92.756 +        
  92.757 +        if (!cachelookup2[phys >> 12])
  92.758 +        {
  92.759 +                readlnum++;
  92.760 +                cycles-=memwaitstate;
  92.761 +                if (cachelookup[cachelnext] != 0xffffffff)
  92.762 +                   cachelookup2[cachelookup[cachelnext]] = 0;
  92.763 +                cachelookup[cachelnext] = phys >> 12;
  92.764 +                cachelookup2[phys >> 12] = 1;
  92.765 +                cachelnext = (cachelnext + 1) & (cachesize - 1);
  92.766 +        }
  92.767 +        
  92.768 +        if (readlookup[readlnext]!=0xFFFFFFFF)
  92.769 +        {
  92.770 +                readlookup2[readlookup[readlnext]]=0xFFFFFFFF;
  92.771 +//                readlnum--;
  92.772 +        }
  92.773 +        readlookup2[virt>>12]=phys&~0xFFF;
  92.774 +        readlookupp[readlnext]=mmu_perm;
  92.775 +        readlookup[readlnext++]=virt>>12;
  92.776 +        readlnext&=(cachesize-1);
  92.777 +}
  92.778 +
  92.779 +void addwritelookup(uint32_t virt, uint32_t phys)
  92.780 +{
  92.781 +//        return;
  92.782 +//        printf("Addwritelookup %08X %08X\n",virt,phys);
  92.783 +        if (writelookup2[virt>>12]!=0xFFFFFFFF)
  92.784 +        {
  92.785 +/*                if (writelookup2[virt>>12] != phys&~0xfff)
  92.786 +                {
  92.787 +                        pclog("addwritelookup mismatch - %05X000 %05X000\n", readlookup[readlnext], virt >> 12);
  92.788 +                        dumpregs();
  92.789 +                        exit(-1);
  92.790 +                }*/
  92.791 +                return;
  92.792 +        }
  92.793 +        
  92.794 +        if (!cachelookup2[phys >> 12])
  92.795 +        {
  92.796 +                writelnum++;
  92.797 +                cycles-=memwaitstate;
  92.798 +                if (cachelookup[cachelnext] != 0xffffffff)
  92.799 +                   cachelookup2[cachelookup[cachelnext]] = 0;
  92.800 +                cachelookup[cachelnext] = phys >> 12;
  92.801 +                cachelookup2[phys >> 12] = 1;
  92.802 +                cachelnext = (cachelnext + 1) & (cachesize - 1);
  92.803 +        }
  92.804 +        
  92.805 +        cycles-=memwaitstate;
  92.806 +        if (writelookup[writelnext]!=0xFFFFFFFF)
  92.807 +        {
  92.808 +                writelookup2[writelookup[writelnext]]=0xFFFFFFFF;
  92.809 +//                writelnum--;
  92.810 +        }
  92.811 +        writelookup2[virt>>12]=phys&~0xFFF;
  92.812 +        writelookupp[writelnext]=mmu_perm;
  92.813 +        writelookup[writelnext++]=virt>>12;
  92.814 +        writelnext&=(cachesize-1);
  92.815 +}
  92.816 +
  92.817 +#undef printf
  92.818 +uint8_t *getpccache(uint32_t a)
  92.819 +{
  92.820 +//        int logit=(a>0xFFFFF);
  92.821 +        uint32_t a2=a;
  92.822 +        if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)];
  92.823 +        if (cr0>>31)
  92.824 +        {
  92.825 +//                if (output==3) pclog("Translate GetPCCache %08X\n",a);
  92.826 +pctrans=1;
  92.827 +                a=mmutranslate(a,0);
  92.828 +                pctrans=0;
  92.829 +//                if (output==3) pclog("GetPCCache output %08X\n",a);
  92.830 +                if (a==0xFFFFFFFF) return ram;
  92.831 +/*                {
  92.832 +                        printf("Bad getpccache %08X\n",a);
  92.833 +                        dumpregs();
  92.834 +                        exit(-1);
  92.835 +                }*/
  92.836 +        }
  92.837 +        a&=rammask;
  92.838 +        //if (output==3) pclog("Getpccache %08X %i\n",a,shadowbios);
  92.839 +        if (isram[a>>16])
  92.840 +        {
  92.841 +                //if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[readlookup2[a>>12]];
  92.842 +                if ((a>>16)!=0xF || shadowbios)
  92.843 +                   addreadlookup(a2,a);
  92.844 +//                if (a > 0xc0000000)
  92.845 +//                   printf("%016X %016X %016X\n", ((long)a&0xFFFFF000), ((long)a2&~0xFFF), (uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF));
  92.846 +                return &ram[(uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF)];
  92.847 +        }
  92.848 +//        if (logit) printf("PCCACHE - %08X -> %08X\n",a2,a);
  92.849 +        switch (a>>16)
  92.850 +        {
  92.851 +                case 0xC: if (a&0x8000) return &romext[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)];
  92.852 +                return &vrom[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)];
  92.853 +                case 0xE: if (shadowbios) return &ram[(uint8_t *)(a&0xFFF000) - (uint8_t *)(a2&~0xFFF)];
  92.854 +                return &rom[(uint8_t *)((a & biosmask) & ~ 0xfff) - (uint8_t *)(a2 & ~0xFFF)];
  92.855 +                case 0xF: if (shadowbios) return &ram[(uint8_t *)(a&0xFFF000) - (uint8_t *)(a2&~0xFFF)];
  92.856 +                return &rom[(uint8_t *)((a & biosmask) & ~ 0xfff) - (uint8_t *)(a2 & ~0xFFF)];
  92.857 +        }
  92.858 +        return &rom[(long)(a&0xF000) - (long)(a2&~0xFFF)];
  92.859 +                        /*printf("Bad getpccache %08X\n",a);
  92.860 +                        dumpregs();
  92.861 +                        exit(-1);*/
  92.862 +}
  92.863 +#define printf pclog
  92.864 +
  92.865 +static uint32_t mem_logical_addr;
  92.866 +uint8_t readmembl(uint32_t addr)
  92.867 +{
  92.868 +        mem_logical_addr = addr;
  92.869 +        if (cr0 >> 31)
  92.870 +        {
  92.871 +                addr = mmutranslate(addr, 0);
  92.872 +                if (addr == 0xFFFFFFFF) return 0xFF;
  92.873 +        }
  92.874 +        addr &= rammask;
  92.875 +
  92.876 +        switch (addr>>16)
  92.877 +        {
  92.878 +                case 13: if (romset==ROM_AMI286) return neat_readems(addr); return 0xFF;
  92.879 +//                case 14: pclog("Read %06X\n", addr); if (shadowbios) { /*printf("Read shadow RAM %08X %02X\n",addr,ram[addr]);*/ return ram[addr]; }
  92.880 +        }
  92.881 +        if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr);
  92.882 +        return 0xFF;
  92.883 +}
  92.884 +
  92.885 +void writemembl(uint32_t addr, uint8_t val)
  92.886 +{
  92.887 +        mem_logical_addr = addr;
  92.888 +
  92.889 +        if (cr0 >> 31)
  92.890 +        {
  92.891 +                addr = mmutranslate(addr,1);
  92.892 +                if (addr == 0xFFFFFFFF) return;
  92.893 +        }
  92.894 +        addr &= rammask;
  92.895 +
  92.896 +        switch (addr>>16)
  92.897 +        {
  92.898 +                case 13: if (romset==ROM_AMI286) neat_writeems(addr,val); return;
  92.899 +//                case 14: printf("Write %08X %02X\n",addr,val); //ram[addr]=val;
  92.900 +//                if (isram[(addr>>16)&0xFF]) ram[addr]=val;
  92.901 +//                return;
  92.902 +        }
  92.903 +        if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val);
  92.904 +//        else                            pclog("Bad write %08X %02X\n", addr, val);
  92.905 +}
  92.906 +
  92.907 +uint8_t readmemb386l(uint32_t seg, uint32_t addr)
  92.908 +{
  92.909 +        if (seg==-1)
  92.910 +        {
  92.911 +                x86gpf("NULL segment", 0);
  92.912 +                printf("NULL segment! rb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
  92.913 +                return -1;
  92.914 +        }
  92.915 +        mem_logical_addr = addr = addr + seg;
  92.916 +        if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF)
  92.917 +        {
  92.918 +                return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)];
  92.919 +        }
  92.920 +        
  92.921 +        if (cr0 >> 31)
  92.922 +        {
  92.923 +                addr = mmutranslate(addr, 0);
  92.924 +                if (addr == 0xFFFFFFFF) return 0xFF;
  92.925 +        }
  92.926 +
  92.927 +        addr &= rammask;
  92.928 +
  92.929 +        if (_mem_read_b[addr >> 15]) return _mem_read_b[addr >> 15](addr);
  92.930 +        return 0xFF;
  92.931 +}
  92.932 +
  92.933 +void writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
  92.934 +{
  92.935 +        if (seg==-1)
  92.936 +        {
  92.937 +                x86gpf("NULL segment", 0);
  92.938 +                printf("NULL segment! wb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
  92.939 +                return;
  92.940 +        }
  92.941 +        
  92.942 +        mem_logical_addr = addr = addr + seg;
  92.943 +        if (cr0 >> 31)
  92.944 +        {
  92.945 +                addr = mmutranslate(addr, 1);
  92.946 +                if (addr == 0xFFFFFFFF) return;
  92.947 +        }
  92.948 +
  92.949 +        addr &= rammask;
  92.950 +
  92.951 +        if (_mem_write_b[addr >> 15]) _mem_write_b[addr >> 15](addr, val);
  92.952 +//        else                            pclog("Bad write %08X %02X\n", addr, val);
  92.953 +}
  92.954 +
  92.955 +uint16_t readmemwl(uint32_t seg, uint32_t addr)
  92.956 +{
  92.957 +        uint32_t addr2 = mem_logical_addr = seg + addr;
  92.958 +        if ((addr2&0xFFF)>0xFFE)
  92.959 +        {
  92.960 +                if (cr0>>31)
  92.961 +                {
  92.962 +                        if (mmutranslate(addr2,   0) == 0xffffffff) return;
  92.963 +                        if (mmutranslate(addr2+1, 0) == 0xffffffff) return;
  92.964 +                }
  92.965 +                if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8);
  92.966 +                else       return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8);
  92.967 +        }
  92.968 +        if (seg==-1)
  92.969 +        {
  92.970 +                x86gpf("NULL segment", 0);
  92.971 +                printf("NULL segment! rw %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
  92.972 +                return -1;
  92.973 +        }
  92.974 +        if (cr0>>31)
  92.975 +        {
  92.976 +                addr2=mmutranslate(addr2,0);
  92.977 +                if (addr2==0xFFFFFFFF) return 0xFFFF;
  92.978 +        }
  92.979 +
  92.980 +        addr2 &= rammask;
  92.981 +
  92.982 +        if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2);
  92.983 +
  92.984 +        if (_mem_read_b[addr2 >> 15])
  92.985 +        {
  92.986 +                if (AT) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[(addr2 + 1) >> 15](addr2 + 1) << 8);
  92.987 +                else    return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff)) << 8);
  92.988 +        }
  92.989 +        return 0xffff;
  92.990 +}
  92.991 +
  92.992 +void writememwl(uint32_t seg, uint32_t addr, uint16_t val)
  92.993 +{
  92.994 +        uint32_t addr2 = mem_logical_addr = seg + addr;
  92.995 +        if ((addr2&0xFFF)>0xFFE)
  92.996 +        {
  92.997 +                if (cr0>>31)
  92.998 +                {
  92.999 +                        if (mmutranslate(addr2,   1) == 0xffffffff) return;
 92.1000 +                        if (mmutranslate(addr2+1, 1) == 0xffffffff) return;
 92.1001 +                }
 92.1002 +                if (is386)
 92.1003 +                {
 92.1004 +                        writememb386l(seg,addr,val);
 92.1005 +                        writememb386l(seg,addr+1,val>>8);
 92.1006 +                }
 92.1007 +                else
 92.1008 +                {
 92.1009 +                        writemembl(seg+addr,val);
 92.1010 +                        writemembl(seg+addr+1,val>>8);
 92.1011 +                }
 92.1012 +                return;
 92.1013 +        }
 92.1014 +
 92.1015 +        if (seg==-1)
 92.1016 +        {
 92.1017 +                x86gpf("NULL segment", 0);
 92.1018 +                printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
 92.1019 +                return;
 92.1020 +        }
 92.1021 +        if (cr0>>31)
 92.1022 +        {
 92.1023 +                addr2=mmutranslate(addr2,1);
 92.1024 +                if (addr2==0xFFFFFFFF) return;
 92.1025 +        }
 92.1026 +        
 92.1027 +        addr2 &= rammask;
 92.1028 +        
 92.1029 +        if (_mem_write_w[addr2 >> 15]) 
 92.1030 +        {
 92.1031 +                _mem_write_w[addr2 >> 15](addr2, val);
 92.1032 +                return;
 92.1033 +        }
 92.1034 +
 92.1035 +        if (_mem_write_b[addr2 >> 15]) 
 92.1036 +        {
 92.1037 +                _mem_write_b[addr2 >> 15](addr2, val);
 92.1038 +                _mem_write_b[(addr2 + 1) >> 15](addr2 + 1, val >> 8);
 92.1039 +//                if (AT) _
 92.1040 +//                else    _mem_write_b[(seg + ((addr + 1) & 0xffff)) >> 15](seg + ((addr + 1) & 0xffff), val >> 8);
 92.1041 +                return;
 92.1042 +        }
 92.1043 +//        pclog("Bad write %08X %04X\n", addr, val);
 92.1044 +}
 92.1045 +
 92.1046 +uint32_t readmemll(uint32_t seg, uint32_t addr)
 92.1047 +{
 92.1048 +        uint32_t addr2 = mem_logical_addr = seg + addr;
 92.1049 +        if ((addr2&0xFFF)>0xFFC)
 92.1050 +        {
 92.1051 +                if (cr0>>31)
 92.1052 +                {
 92.1053 +                        if (mmutranslate(addr2,   0) == 0xffffffff) return;
 92.1054 +                        if (mmutranslate(addr2+3, 0) == 0xffffffff) return;
 92.1055 +                }
 92.1056 +                return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
 92.1057 +        }
 92.1058 +
 92.1059 +        if (seg==-1)
 92.1060 +        {
 92.1061 +                x86gpf("NULL segment", 0);
 92.1062 +                printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
 92.1063 +                return -1;
 92.1064 +        }
 92.1065 +        
 92.1066 +        if (cr0>>31)
 92.1067 +        {
 92.1068 +                addr2=mmutranslate(addr2,0);
 92.1069 +                if (addr2==0xFFFFFFFF) return 0xFFFFFFFF;
 92.1070 +        }
 92.1071 +
 92.1072 +        addr2&=rammask;
 92.1073 +
 92.1074 +        if (_mem_read_l[addr2 >> 15]) return _mem_read_l[addr2 >> 15](addr2);
 92.1075 +
 92.1076 +        if (_mem_read_w[addr2 >> 15]) return _mem_read_w[addr2 >> 15](addr2) | (_mem_read_w[addr2 >> 15](addr2 + 2) << 16);
 92.1077 +        
 92.1078 +        if (_mem_read_b[addr2 >> 15]) return _mem_read_b[addr2 >> 15](addr2) | (_mem_read_b[addr2 >> 15](addr2 + 1) << 8) | (_mem_read_b[addr2 >> 15](addr2 + 2) << 16) | (_mem_read_b[addr2 >> 15](addr2 + 3) << 24);
 92.1079 +
 92.1080 +        return 0xffffffff;
 92.1081 +}
 92.1082 +
 92.1083 +void writememll(uint32_t seg, uint32_t addr, uint32_t val)
 92.1084 +{
 92.1085 +        uint32_t addr2 = mem_logical_addr = seg + addr;
 92.1086 +
 92.1087 +        if ((addr2&0xFFF)>0xFFC)
 92.1088 +        {
 92.1089 +                if (cr0>>31)
 92.1090 +                {
 92.1091 +                        if (mmutranslate(addr2,   1) == 0xffffffff) return;
 92.1092 +                        if (mmutranslate(addr2+3, 1) == 0xffffffff) return;
 92.1093 +                }
 92.1094 +                writememwl(seg,addr,val);
 92.1095 +                writememwl(seg,addr+2,val>>16);
 92.1096 +                return;
 92.1097 +        }
 92.1098 +        if (seg==-1)
 92.1099 +        {
 92.1100 +                x86gpf("NULL segment", 0);
 92.1101 +                printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
 92.1102 +                return;
 92.1103 +        }
 92.1104 +        if (cr0>>31)
 92.1105 +        {
 92.1106 +                addr2=mmutranslate(addr2,1);
 92.1107 +                if (addr2==0xFFFFFFFF) return;
 92.1108 +        }
 92.1109 +        
 92.1110 +        addr2&=rammask;
 92.1111 +
 92.1112 +        if (_mem_write_l[addr2 >> 15]) 
 92.1113 +        {
 92.1114 +                _mem_write_l[addr2 >> 15](addr2, val);
 92.1115 +                return;
 92.1116 +        }
 92.1117 +        if (_mem_write_w[addr2 >> 15]) 
 92.1118 +        {
 92.1119 +                _mem_write_w[addr2 >> 15](addr2,     val);
 92.1120 +                _mem_write_w[addr2 >> 15](addr2 + 2, val >> 16);
 92.1121 +                return;
 92.1122 +        }
 92.1123 +        if (_mem_write_b[addr2 >> 15]) 
 92.1124 +        {
 92.1125 +                _mem_write_b[addr2 >> 15](addr2,     val);
 92.1126 +                _mem_write_b[addr2 >> 15](addr2 + 1, val >> 8);
 92.1127 +                _mem_write_b[addr2 >> 15](addr2 + 2, val >> 16);
 92.1128 +                _mem_write_b[addr2 >> 15](addr2 + 3, val >> 24);
 92.1129 +                return;
 92.1130 +        }
 92.1131 +//        pclog("Bad write %08X %08X\n", addr, val);
 92.1132 +}
 92.1133 +
 92.1134 +uint8_t mem_read_ram(uint32_t addr)
 92.1135 +{
 92.1136 +//        if (addr < 0xa0000) pclog("Read RAMb %08X\n", addr);
 92.1137 +        addreadlookup(mem_logical_addr, addr);
 92.1138 +        return ram[addr];
 92.1139 +}
 92.1140 +uint16_t mem_read_ramw(uint32_t addr)
 92.1141 +{
 92.1142 +//        if (addr < 0xa0000) pclog("Read RAMw %08X\n", addr);
 92.1143 +        addreadlookup(mem_logical_addr, addr);
 92.1144 +        return *(uint16_t *)&ram[addr];
 92.1145 +}
 92.1146 +uint32_t mem_read_raml(uint32_t addr)
 92.1147 +{
 92.1148 +//        if (addr < 0xa0000) pclog("Read RAMl %08X\n", addr);
 92.1149 +        addreadlookup(mem_logical_addr, addr);
 92.1150 +        return *(uint32_t *)&ram[addr];
 92.1151 +}
 92.1152 +
 92.1153 +void mem_write_ram(uint32_t addr, uint8_t val)
 92.1154 +{
 92.1155 +        addwritelookup(mem_logical_addr, addr);
 92.1156 +        ram[addr] = val;
 92.1157 +//        if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMb %08X\n", addr);
 92.1158 +}
 92.1159 +void mem_write_ramw(uint32_t addr, uint16_t val)
 92.1160 +{
 92.1161 +        addwritelookup(mem_logical_addr, addr);
 92.1162 +        *(uint16_t *)&ram[addr] = val;
 92.1163 +//        if (addr >= 0xe0000 && addr < 0x100000)  pclog("Write RAMw %08X %04X:%04X\n", addr, CS, pc);
 92.1164 +}
 92.1165 +void mem_write_raml(uint32_t addr, uint32_t val)
 92.1166 +{
 92.1167 +        addwritelookup(mem_logical_addr, addr);
 92.1168 +        *(uint32_t *)&ram[addr] = val;
 92.1169 +//        if (addr >= 0xe0000 && addr < 0x100000) pclog("Write RAMl %08X  %04X:%04X  %04X:%04X  %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI);
 92.1170 +}
 92.1171 +
 92.1172 +uint8_t mem_read_bios(uint32_t addr)
 92.1173 +{
 92.1174 +                        if (AMIBIOS && (addr&0xFFFFF)==0xF8281) /*This is read constantly during AMIBIOS POST, but is never written to. It's clearly a status register of some kind, but for what?*/
 92.1175 +                        {
 92.1176 +//                                pclog("Read magic addr %04X(%06X):%04X\n",CS,cs,pc);
 92.1177 +//                                if (pc==0x547D) output=3;
 92.1178 +                                return 0x40;
 92.1179 +                        }
 92.1180 +//        if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc);
 92.1181 +        return rom[addr & biosmask];
 92.1182 +}
 92.1183 +uint16_t mem_read_biosw(uint32_t addr)
 92.1184 +{
 92.1185 +//        if (output) pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc);
 92.1186 +        return *(uint16_t *)&rom[addr & biosmask];
 92.1187 +}
 92.1188 +uint32_t mem_read_biosl(uint32_t addr)
 92.1189 +{
 92.1190 +//        if (output) pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc);
 92.1191 +        return *(uint32_t *)&rom[addr & biosmask];
 92.1192 +}
 92.1193 +
 92.1194 +uint8_t mem_read_vrom(uint32_t addr)
 92.1195 +{
 92.1196 +        return vrom[addr & 0x7fff];
 92.1197 +}
 92.1198 +uint16_t mem_read_vromw(uint32_t addr)
 92.1199 +{
 92.1200 +        return *(uint16_t *)&vrom[addr & 0x7fff];
 92.1201 +}
 92.1202 +uint32_t mem_read_vroml(uint32_t addr)
 92.1203 +{
 92.1204 +        return *(uint32_t *)&vrom[addr & 0x7fff];
 92.1205 +}
 92.1206 +
 92.1207 +uint8_t mem_read_romext(uint32_t addr)
 92.1208 +{
 92.1209 +        return romext[addr & 0x7fff];
 92.1210 +}
 92.1211 +uint16_t mem_read_romextw(uint32_t addr)
 92.1212 +{
 92.1213 +        return *(uint16_t *)&romext[addr & 0x7fff];
 92.1214 +}
 92.1215 +uint32_t mem_read_romextl(uint32_t addr)
 92.1216 +{
 92.1217 +        return *(uint32_t *)&romext[addr & 0x7fff];
 92.1218 +}
 92.1219 +
 92.1220 +void mem_init()
 92.1221 +{
 92.1222 +        int c;
 92.1223 +        ram=malloc(mem_size*1024*1024);
 92.1224 +        rom=malloc(0x20000);
 92.1225 +        vram=malloc(0x800000);
 92.1226 +        vrom=malloc(0x8000);
 92.1227 +        readlookup2=malloc(1024*1024*4);
 92.1228 +        writelookup2=malloc(1024*1024*4);
 92.1229 +        cachelookup2=malloc(1024*1024);
 92.1230 +        biosmask=65535;
 92.1231 +        makeznptable();
 92.1232 +        memset(ram,0,mem_size*1024*1024);
 92.1233 +        for (c = 0; c < 0x10000; c++) isram[c] = 0;
 92.1234 +        for (c=0;c<(mem_size*16);c++)
 92.1235 +        {
 92.1236 +                isram[c]=1;
 92.1237 +                if (c >= 0xa && c<=0xF) isram[c]=0;
 92.1238 +        }
 92.1239 +        for (c = 0; c < 0x20000; c++)
 92.1240 +            _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL;
 92.1241 +
 92.1242 +        mem_sethandler(0x00000, 0xa0000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml);
 92.1243 +        if (mem_size > 1)
 92.1244 +           mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml);            
 92.1245 +           
 92.1246 +        mem_sethandler(0xc0000, 0x08000, mem_read_vrom,   mem_read_vromw,   mem_read_vroml,   NULL, NULL, NULL);
 92.1247 +        mem_sethandler(0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL);
 92.1248 +        mem_sethandler(0xe0000, 0x20000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml);
 92.1249 +//        pclog("Mem resize %i %i\n",mem_size,c);
 92.1250 +}
 92.1251 +
 92.1252 +void mem_resize()
 92.1253 +{
 92.1254 +        int c;
 92.1255 +        free(ram);
 92.1256 +        ram=malloc(mem_size*1024*1024);
 92.1257 +        memset(ram,0,mem_size*1024*1024);
 92.1258 +        for (c = 0; c < 0x10000; c++) isram[c] = 0;
 92.1259 +        for (c=0;c<(mem_size*16);c++)
 92.1260 +        {
 92.1261 +                isram[c]=1;
 92.1262 +                if (c >= 0xa && c<=0xF) isram[c]=0;
 92.1263 +        }
 92.1264 +        for (c = 0; c < 0x20000; c++)
 92.1265 +            _mem_read_b[c] = _mem_read_w[c] = _mem_read_l[c] = _mem_write_b[c] = _mem_write_w[c] = _mem_write_l[c] = NULL;
 92.1266 +
 92.1267 +        mem_sethandler(0x00000, 0xa0000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml);
 92.1268 +        if (mem_size > 1)
 92.1269 +           mem_sethandler(0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml);            
 92.1270 +
 92.1271 +        mem_sethandler(0xc0000, 0x8000, mem_read_vrom,   mem_read_vromw,   mem_read_vroml,   NULL, NULL, NULL);
 92.1272 +        mem_sethandler(0xc8000, 0x8000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL);        
 92.1273 +        mem_sethandler(0xe0000, 0x20000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml);
 92.1274 +//        pclog("Mem resize %i %i\n",mem_size,c);
 92.1275 +}
 92.1276 +
 92.1277 +void mem_updatecache()
 92.1278 +{
 92.1279 +        flushmmucache();
 92.1280 +        if (!is386)
 92.1281 +        {
 92.1282 +                cachesize=256;
 92.1283 +                memwaitstate=0;
 92.1284 +                return;
 92.1285 +        }
 92.1286 +        if (cpu_16bitbus)
 92.1287 +           memwaitstate = 512 * cpu_multi;
 92.1288 +        else
 92.1289 +           memwaitstate = 384 * cpu_multi; //memspeed[cpuspeed];        
 92.1290 +        switch (cache)
 92.1291 +        {
 92.1292 +                case 0: cachesize=32; break;
 92.1293 +                case 1: cachesize=64; break;
 92.1294 +                case 2: cachesize=128; break;
 92.1295 +                case 3: cachesize=256; break;
 92.1296 +                case 4: cachesize=256; memwaitstate=0; break;
 92.1297 +        }
 92.1298 +}
 92.1299 +
 92.1300 +void mem_sethandler(uint32_t base, uint32_t size, 
 92.1301 +                    uint8_t  (*read_b)(uint32_t addr),
 92.1302 +                    uint16_t (*read_w)(uint32_t addr),
 92.1303 +                    uint32_t (*read_l)(uint32_t addr),
 92.1304 +                    void (*write_b)(uint32_t addr, uint8_t  val),
 92.1305 +                    void (*write_w)(uint32_t addr, uint16_t val),
 92.1306 +                    void (*write_l)(uint32_t addr, uint32_t val))
 92.1307 +{
 92.1308 +        uint32_t c;
 92.1309 +        for (c = base; c < base + size; c += 0x8000)
 92.1310 +        {
 92.1311 +                _mem_read_b[ c >> 15] =  read_b;
 92.1312 +                _mem_read_w[ c >> 15] =  read_w;
 92.1313 +                _mem_read_l[ c >> 15] =  read_l;
 92.1314 +                _mem_write_b[c >> 15] = write_b;
 92.1315 +                _mem_write_w[c >> 15] = write_w;
 92.1316 +                _mem_write_l[c >> 15] = write_l;
 92.1317 +        }
 92.1318 +}
 92.1319 +
 92.1320 +void mem_removehandler(uint32_t base, uint32_t size, 
 92.1321 +                       uint8_t  (*read_b)(uint32_t addr),
 92.1322 +                       uint16_t (*read_w)(uint32_t addr),
 92.1323 +                       uint32_t (*read_l)(uint32_t addr),
 92.1324 +                       void (*write_b)(uint32_t addr, uint8_t  val),
 92.1325 +                       void (*write_w)(uint32_t addr, uint16_t val),
 92.1326 +                       void (*write_l)(uint32_t addr, uint32_t val))
 92.1327 +{
 92.1328 +        uint32_t c;
 92.1329 +        if ((base + size) > 0xffff8000)
 92.1330 +           size = 0xffff0000 - base;
 92.1331 +        for (c = base; c < base + size; c += 0x8000)
 92.1332 +        {
 92.1333 +                if ( _mem_read_b[c >> 15]  == read_b)  _mem_read_b[c >> 15] = NULL;
 92.1334 +                if ( _mem_read_w[c >> 15]  == read_w)  _mem_read_w[c >> 15] = NULL;
 92.1335 +                if ( _mem_read_l[c >> 15]  == read_l)  _mem_read_l[c >> 15] = NULL;
 92.1336 +                if (_mem_write_b[c >> 15] == write_b) _mem_write_b[c >> 15] = NULL;
 92.1337 +                if (_mem_write_w[c >> 15] == write_w) _mem_write_w[c >> 15] = NULL;
 92.1338 +                if (_mem_write_l[c >> 15] == write_l) _mem_write_l[c >> 15] = NULL;                                
 92.1339 +        }
 92.1340 +}
 92.1341 +
 92.1342 +int mem_a20_key = 0, mem_a20_alt = 0;
 92.1343 +static int mem_a20_state = 0;
 92.1344 +
 92.1345 +void mem_a20_recalc()
 92.1346 +{
 92.1347 +        int state = mem_a20_key | mem_a20_alt;
 92.1348 +        pclog("A20 recalc %i %i\n", state, mem_a20_state);
 92.1349 +        if (state && !mem_a20_state)
 92.1350 +        {
 92.1351 +                rammask = 0xffffffff;
 92.1352 +                flushmmucache();
 92.1353 +        }
 92.1354 +        else if (!state && mem_a20_state)
 92.1355 +        {
 92.1356 +                rammask = 0xffefffff;
 92.1357 +                flushmmucache();
 92.1358 +        }
 92.1359 +        pclog("rammask now %08X\n", rammask);
 92.1360 +        mem_a20_state = state;
 92.1361 +}
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/src/mem.h	Sun Apr 21 14:54:35 2013 +0100
    93.3 @@ -0,0 +1,40 @@
    93.4 +extern uint8_t *ram,*rom,*vram,*vrom;
    93.5 +extern uint8_t romext[32768];
    93.6 +extern int readlnum,writelnum;
    93.7 +extern int memspeed[11];
    93.8 +extern int nopageerrors;
    93.9 +extern int cache;
   93.10 +extern int memwaitstate;
   93.11 +
   93.12 +void mem_sethandler(uint32_t base, uint32_t size, 
   93.13 +                    uint8_t  (*read_b)(uint32_t addr),
   93.14 +                    uint16_t (*read_w)(uint32_t addr),
   93.15 +                    uint32_t (*read_l)(uint32_t addr),
   93.16 +                    void (*write_b)(uint32_t addr, uint8_t  val),
   93.17 +                    void (*write_w)(uint32_t addr, uint16_t val),
   93.18 +                    void (*write_l)(uint32_t addr, uint32_t val));
   93.19 +
   93.20 +void mem_removehandler(uint32_t base, uint32_t size, 
   93.21 +                       uint8_t  (*read_b)(uint32_t addr),
   93.22 +                       uint16_t (*read_w)(uint32_t addr),
   93.23 +                       uint32_t (*read_l)(uint32_t addr),
   93.24 +                       void (*write_b)(uint32_t addr, uint8_t  val),
   93.25 +                       void (*write_w)(uint32_t addr, uint16_t val),
   93.26 +                       void (*write_l)(uint32_t addr, uint32_t val));
   93.27 +extern int mem_a20_alt;
   93.28 +extern int mem_a20_key;
   93.29 +void mem_a20_recalc();
   93.30 +
   93.31 +uint8_t  mem_read_ram(uint32_t addr);
   93.32 +uint16_t mem_read_ramw(uint32_t addr);
   93.33 +uint32_t mem_read_raml(uint32_t addr);
   93.34 +
   93.35 +void mem_write_ram(uint32_t addr, uint8_t val);
   93.36 +void mem_write_ramw(uint32_t addr, uint16_t val);
   93.37 +void mem_write_raml(uint32_t addr, uint32_t val);
   93.38 +
   93.39 +uint8_t  mem_read_bios(uint32_t addr);
   93.40 +uint16_t mem_read_biosw(uint32_t addr);
   93.41 +uint32_t mem_read_biosl(uint32_t addr);
   93.42 +
   93.43 +FILE *romfopen(char *fn, char *mode);
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/src/model.c	Sun Apr 21 14:54:35 2013 +0100
    94.3 @@ -0,0 +1,200 @@
    94.4 +#include "ibm.h"
    94.5 +#include "cpu.h"
    94.6 +#include "model.h"
    94.7 +#include "io.h"
    94.8 +
    94.9 +#include "acer386sx.h"
   94.10 +#include "ali1429.h"
   94.11 +#include "amstrad.h"
   94.12 +#include "dma.h"
   94.13 +#include "fdc.h"
   94.14 +#include "headland.h"
   94.15 +#include "ide.h"
   94.16 +#include "jim.h"
   94.17 +#include "keyboard_xt.h"
   94.18 +#include "keyboard_at.h"
   94.19 +#include "keyboard_olim24.h"
   94.20 +#include "lpt.h"
   94.21 +#include "mouse_ps2.h"
   94.22 +#include "mouse_serial.h"
   94.23 +#include "neat.h"
   94.24 +#include "nvr.h"
   94.25 +#include "olivetti_m24.h"
   94.26 +#include "pci.h"
   94.27 +#include "pic.h"
   94.28 +#include "pit.h"
   94.29 +#include "psg.h"
   94.30 +#include "serial.h"
   94.31 +#include "um8881f.h"
   94.32 +#include "wd76c10.h"
   94.33 +#include "xtide.h"
   94.34 +
   94.35 +void           xt_init();
   94.36 +void      tandy1k_init();
   94.37 +void          ams_init();
   94.38 +void       europc_init();
   94.39 +void       olim24_init();
   94.40 +void           at_init();
   94.41 +void      at_neat_init();
   94.42 +void at_acer386sx_init();
   94.43 +void   at_wd76c10_init();
   94.44 +void   at_ali1429_init();
   94.45 +void  at_headland_init();
   94.46 +void   at_um8881f_init();
   94.47 +
   94.48 +int model;
   94.49 +
   94.50 +MODEL models[] =
   94.51 +{
   94.52 +        {"IBM PC",              ROM_IBMPC,     { "",      cpus_8088,  "",    NULL,       "",      NULL},         0,      xt_init},
   94.53 +        {"IBM XT",              ROM_IBMXT,     { "",      cpus_8088,  "",    NULL,       "",      NULL},         0,      xt_init},
   94.54 +        {"Generic XT clone",    ROM_GENXT,     { "",      cpus_8088,  "",    NULL,       "",      NULL},         0,      xt_init},
   94.55 +        {"DTK XT clone",        ROM_DTKXT,     { "",      cpus_8088,  "",    NULL,       "",      NULL},         0,      xt_init},        
   94.56 +        {"Tandy 1000",          ROM_TANDY,     { "",      cpus_8088,  "",    NULL,       "",      NULL},         1, tandy1k_init},
   94.57 +        {"Amstrad PC1512",      ROM_PC1512,    { "",      cpus_pc1512,"",    NULL,       "",      NULL},         1,     ams_init},
   94.58 +        {"Sinclair PC200",      ROM_PC200,     { "",      cpus_8086,  "",    NULL,       "",      NULL},         1,     ams_init},
   94.59 +        {"Euro PC",             ROM_EUROPC,    { "",      cpus_8086,  "",    NULL,       "",      NULL},         0,  europc_init},
   94.60 +        {"Olivetti M24",        ROM_OLIM24,    { "",      cpus_8086,  "",    NULL,       "",      NULL},         1,  olim24_init},        
   94.61 +        {"Amstrad PC1640",      ROM_PC1640,    { "",      cpus_8086,  "",    NULL,       "",      NULL},         1,     ams_init},
   94.62 +        {"Amstrad PC2086",      ROM_PC2086,    { "",      cpus_8086,  "",    NULL,       "",      NULL},         1,     ams_init},        
   94.63 +        {"Amstrad PC3086",      ROM_PC3086,    { "",      cpus_8086,  "",    NULL,       "",      NULL},         1,     ams_init},
   94.64 +        {"IBM AT",              ROM_IBMAT,     { "",      cpus_ibmat, "",    NULL,       "",      NULL},         0,      at_init},
   94.65 +        {"Commodore PC 30 III", ROM_CMDPC30,   { "",      cpus_286,   "",    NULL,       "",      NULL},         0,      at_init},        
   94.66 +        {"AMI 286 clone",       ROM_AMI286,    { "",      cpus_286,   "",    NULL,       "",      NULL},         0,     at_neat_init},        
   94.67 +        {"DELL System 200",     ROM_DELL200,   { "",      cpus_286,   "",    NULL,       "",      NULL},         0,      at_init},
   94.68 +        {"Acer 386SX25/N",      ROM_ACER386,   { "Intel", cpus_acer,  "",    NULL,       "",      NULL},         1, at_acer386sx_init},
   94.69 +        {"Amstrad MegaPC",      ROM_MEGAPC,    { "Intel", cpus_i386,  "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1,   at_wd76c10_init},
   94.70 +        {"AMI 386 clone",       ROM_AMI386,    { "Intel", cpus_i386,  "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0,  at_headland_init},
   94.71 +        {"AMI 486 clone",       ROM_AMI486,    { "Intel", cpus_i486,  "AMD", cpus_Am486, "Cyrix", cpus_Cx486},   0,   at_ali1429_init},
   94.72 +        {"AMI WinBIOS 486",     ROM_WIN486,    { "Intel", cpus_i486,  "AMD", cpus_Am486, "Cyrix", cpus_Cx486},   0,   at_ali1429_init},
   94.73 +        {"AMI WinBIOS 486 PCI", ROM_PCI486,    { "Intel", cpus_i486,  "AMD", cpus_Am486, "Cyrix", cpus_Cx486},   0,   at_um8881f_init},
   94.74 +        {"", -1, {"", 0, "", 0, "", 0}, 0}
   94.75 +};
   94.76 +
   94.77 +int model_getromset()
   94.78 +{
   94.79 +        return models[model].id;
   94.80 +}
   94.81 +
   94.82 +char *model_getname()
   94.83 +{
   94.84 +        return models[model].name;
   94.85 +}
   94.86 +
   94.87 +void common_init()
   94.88 +{
   94.89 +        dma_init();
   94.90 +        fdc_init();
   94.91 +        lpt_init();
   94.92 +        pic_init();
   94.93 +        pit_init();
   94.94 +        serial1_init(0x3f8);
   94.95 +        serial2_init(0x2f8);
   94.96 +}
   94.97 +
   94.98 +void xt_init()
   94.99 +{
  94.100 +        common_init();
  94.101 +        keyboard_xt_init();
  94.102 +        mouse_serial_init();
  94.103 +        xtide_init();
  94.104 +}
  94.105 +
  94.106 +void tandy1k_init()
  94.107 +{
  94.108 +        common_init();
  94.109 +        keyboard_xt_init();
  94.110 +        mouse_serial_init();
  94.111 +        psg_init();
  94.112 +        xtide_init();
  94.113 +}
  94.114 +
  94.115 +void ams_init()
  94.116 +{
  94.117 +        common_init();
  94.118 +        amstrad_init();
  94.119 +        keyboard_amstrad_init();
  94.120 +        nvr_init();
  94.121 +        xtide_init();
  94.122 +}
  94.123 +
  94.124 +void europc_init()
  94.125 +{
  94.126 +        common_init();
  94.127 +        jim_init();
  94.128 +        keyboard_xt_init();
  94.129 +        mouse_serial_init();
  94.130 +        xtide_init();
  94.131 +}
  94.132 +
  94.133 +void olim24_init()
  94.134 +{
  94.135 +        common_init();
  94.136 +        keyboard_olim24_init();
  94.137 +        nvr_init();
  94.138 +        olivetti_m24_init();
  94.139 +        xtide_init();
  94.140 +}
  94.141 +
  94.142 +void at_init()
  94.143 +{
  94.144 +        common_init();
  94.145 +        dma16_init();
  94.146 +        ide_init();
  94.147 +        keyboard_at_init();
  94.148 +        if (models[model].init == at_init)
  94.149 +           mouse_serial_init();
  94.150 +        nvr_init();
  94.151 +        pic2_init();
  94.152 +}
  94.153 +
  94.154 +void at_neat_init()
  94.155 +{
  94.156 +        at_init();
  94.157 +        mouse_serial_init();
  94.158 +        neat_init();
  94.159 +}
  94.160 +
  94.161 +void at_acer386sx_init()
  94.162 +{
  94.163 +        at_init();
  94.164 +        mouse_ps2_init();
  94.165 +        acer386sx_init();
  94.166 +}
  94.167 +
  94.168 +void at_wd76c10_init()
  94.169 +{
  94.170 +        at_init();
  94.171 +        mouse_ps2_init();
  94.172 +        wd76c10_init();
  94.173 +}
  94.174 +
  94.175 +void at_headland_init()
  94.176 +{
  94.177 +        at_init();
  94.178 +        headland_init();
  94.179 +        mouse_serial_init();
  94.180 +}
  94.181 +
  94.182 +void at_ali1429_init()
  94.183 +{
  94.184 +        at_init();
  94.185 +        ali1429_init();
  94.186 +        mouse_serial_init();
  94.187 +}
  94.188 +
  94.189 +void at_um8881f_init()
  94.190 +{
  94.191 +        at_init();
  94.192 +        mouse_serial_init();
  94.193 +        pci_init();
  94.194 +        um8881f_init();
  94.195 +}
  94.196 +
  94.197 +void model_init()
  94.198 +{
  94.199 +        pclog("Initting as %s\n", model_getname());
  94.200 +        io_init();
  94.201 +        
  94.202 +        models[model].init();
  94.203 +}
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/src/model.h	Sun Apr 21 14:54:35 2013 +0100
    95.3 @@ -0,0 +1,16 @@
    95.4 +typedef struct
    95.5 +{
    95.6 +        char name[24];
    95.7 +        int id;
    95.8 +        struct
    95.9 +        {
   95.10 +                char name[8];
   95.11 +                CPU *cpus;
   95.12 +        } cpu[3];
   95.13 +        int fixed_gfxcard;
   95.14 +        void (*init)();
   95.15 +} MODEL;
   95.16 +
   95.17 +extern MODEL models[];
   95.18 +
   95.19 +extern int model;
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/src/mouse.c	Sun Apr 21 14:54:35 2013 +0100
    96.3 @@ -0,0 +1,4 @@
    96.4 +#include "ibm.h"
    96.5 +#include "mouse.h"
    96.6 +
    96.7 +void (*mouse_poll)(int x, int y, int b);
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/src/mouse.h	Sun Apr 21 14:54:35 2013 +0100
    97.3 @@ -0,0 +1,5 @@
    97.4 +extern void (*mouse_poll)(int x, int y, int b);
    97.5 +
    97.6 +extern int mousepos;
    97.7 +extern int mousedelay;
    97.8 +
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/src/mouse_ps2.c	Sun Apr 21 14:54:35 2013 +0100
    98.3 @@ -0,0 +1,152 @@
    98.4 +#include "ibm.h"
    98.5 +#include "keyboard_at.h"
    98.6 +#include "mouse.h"
    98.7 +#include "mouse_ps2.h"
    98.8 +#include "plat-mouse.h"
    98.9 +
   98.10 +enum
   98.11 +{
   98.12 +        MOUSE_STREAM,
   98.13 +        MOUSE_REMOTE,
   98.14 +        MOUSE_ECHO
   98.15 +};
   98.16 +
   98.17 +#define MOUSE_ENABLE 0x20
   98.18 +#define MOUSE_SCALE  0x10
   98.19 +
   98.20 +static struct
   98.21 +{
   98.22 +        int mode;
   98.23 +        
   98.24 +        uint8_t flags;
   98.25 +        uint8_t resolution;
   98.26 +        
   98.27 +        uint8_t command;
   98.28 +        
   98.29 +        int cd;
   98.30 +} mouse_ps2;
   98.31 +
   98.32 +void mouse_ps2_write(uint8_t val)
   98.33 +{
   98.34 +        if (mouse_ps2.cd)
   98.35 +        {
   98.36 +                mouse_ps2.cd = 0;
   98.37 +                switch (mouse_ps2.command)
   98.38 +                {
   98.39 +                        case 0xe8: /*Set mouse resolution*/
   98.40 +                        mouse_ps2.resolution = val;
   98.41 +                        keyboard_at_adddata_mouse(0xfa);
   98.42 +                        break;
   98.43 +                        
   98.44 +                        case 0xf3: /*Set sample rate*/
   98.45 +                        keyboard_at_adddata_mouse(0xfa);
   98.46 +                        break;
   98.47 +                        
   98.48 +//                        default:
   98.49 +//                        fatal("mouse_ps2 : Bad data write %02X for command %02X\n", val, mouse_ps2.command);
   98.50 +                }
   98.51 +        }
   98.52 +        else
   98.53 +        {
   98.54 +                mouse_ps2.command = val;
   98.55 +                switch (mouse_ps2.command)
   98.56 +                {
   98.57 +                        case 0xe6: /*Set scaling to 1:1*/
   98.58 +                        mouse_ps2.flags &= ~MOUSE_SCALE;
   98.59 +                        keyboard_at_adddata_mouse(0xfa);
   98.60 +                        break;
   98.61 +
   98.62 +                        case 0xe7: /*Set scaling to 2:1*/
   98.63 +                        mouse_ps2.flags |= MOUSE_SCALE;
   98.64 +                        keyboard_at_adddata_mouse(0xfa);
   98.65 +                        break;
   98.66 +                        
   98.67 +                        case 0xe8: /*Set mouse resolution*/
   98.68 +                        mouse_ps2.cd = 1;
   98.69 +                        keyboard_at_adddata_mouse(0xfa);
   98.70 +                        break;
   98.71 +
   98.72 +                        case 0xf2: /*Read ID*/
   98.73 +                        keyboard_at_adddata_mouse(0xfa);
   98.74 +                        keyboard_at_adddata_mouse(0x00);
   98.75 +                        break;
   98.76 +                        
   98.77 +                        case 0xf3: /*Set sample rate*/
   98.78 +                        mouse_ps2.cd = 1;
   98.79 +                        keyboard_at_adddata_mouse(0xfa);
   98.80 +                        break;
   98.81 +
   98.82 +                        case 0xf4: /*Enable*/
   98.83 +                        mouse_ps2.flags |= MOUSE_ENABLE;
   98.84 +                        keyboard_at_adddata_mouse(0xfa);
   98.85 +                        break;
   98.86 +                                                
   98.87 +                        case 0xf5: /*Disable*/
   98.88 +                        mouse_ps2.flags &= ~MOUSE_ENABLE;
   98.89 +                        keyboard_at_adddata_mouse(0xfa);
   98.90 +                        break;
   98.91 +                        
   98.92 +                        case 0xff: /*Reset*/
   98.93 +                        mouse_ps2.mode  = MOUSE_STREAM;
   98.94 +                        mouse_ps2.flags = 0;
   98.95 +                        keyboard_at_adddata_mouse(0xfa);
   98.96 +                        keyboard_at_adddata_mouse(0xaa);
   98.97 +                        keyboard_at_adddata_mouse(0x00);
   98.98 +                        break;
   98.99 +                        
  98.100 +//                        default:
  98.101 +//                        fatal("mouse_ps2 : Bad command %02X\n", val, mouse_ps2.command);
  98.102 +                }
  98.103 +        }
  98.104 +}
  98.105 +
  98.106 +static int ps2_x = 0, ps2_y = 0, ps2_b = 0;
  98.107 +void mouse_ps2_poll(int x, int y, int b)
  98.108 +{
  98.109 +        uint8_t packet[3] = {0x08, 0, 0};
  98.110 +        if (!x && !y && b == ps2_b) return;        
  98.111 +        ps2_x += x;
  98.112 +        ps2_y -= y;        
  98.113 +        if (mouse_ps2.mode == MOUSE_STREAM && (mouse_ps2.flags & MOUSE_ENABLE) &&
  98.114 +            ((mouse_queue_end - mouse_queue_start) & 0xf) < 13)
  98.115 +        {
  98.116 +                ps2_b  = b;
  98.117 +               // pclog("Send packet : %i %i\n", ps2_x, ps2_y);
  98.118 +                if (ps2_x > 255)
  98.119 +                   ps2_x = 255;
  98.120 +                if (ps2_x < -256)
  98.121 +                   ps2_x = -256;
  98.122 +                if (ps2_y > 255)
  98.123 +                   ps2_y = 255;
  98.124 +                if (ps2_y < -256)
  98.125 +                   ps2_y = -256;
  98.126 +                if (ps2_x < 0)
  98.127 +                   packet[0] |= 0x10;
  98.128 +                if (ps2_y < 0)
  98.129 +                   packet[0] |= 0x20;
  98.130 +                if (mouse_b & 1)
  98.131 +                   packet[0] |= 1;
  98.132 +                if (mouse_b & 2)
  98.133 +                   packet[0] |= 2;
  98.134 +                if (mouse_b & 4)
  98.135 +                   packet[0] |= 4;
  98.136 +                packet[1] = ps2_x & 0xff;
  98.137 +                packet[2] = ps2_y & 0xff;
  98.138 +                
  98.139 +                ps2_x = ps2_y = 0;
  98.140 +                
  98.141 +                keyboard_at_adddata_mouse(packet[0]);
  98.142 +                keyboard_at_adddata_mouse(packet[1]);
  98.143 +                keyboard_at_adddata_mouse(packet[2]);
  98.144 +        }
  98.145 +}
  98.146 +
  98.147 +
  98.148 +void mouse_ps2_init()
  98.149 +{
  98.150 +        mouse_poll  = mouse_ps2_poll;
  98.151 +        mouse_write = mouse_ps2_write;
  98.152 +        mouse_ps2.cd = 0;
  98.153 +        mouse_ps2.flags = 0;
  98.154 +        mouse_ps2.mode = MOUSE_STREAM;
  98.155 +}
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/src/mouse_ps2.h	Sun Apr 21 14:54:35 2013 +0100
    99.3 @@ -0,0 +1,1 @@
    99.4 +void mouse_ps2_init();
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/src/mouse_serial.c	Sun Apr 21 14:54:35 2013 +0100
   100.3 @@ -0,0 +1,66 @@
   100.4 +#include "ibm.h"
   100.5 +#include "mouse.h"
   100.6 +#include "serial.h"
   100.7 +
   100.8 +static int oldb=0;
   100.9 +
  100.10 +void mouse_serial_poll(int x, int y, int b)
  100.11 +{
  100.12 +        uint8_t mousedat[3];
  100.13 +        
  100.14 +        if (!(serial.ier&1)) return;
  100.15 +        if (!x && !y && b==oldb) return;
  100.16 +
  100.17 +        oldb=b;
  100.18 +        if (x>127) x=127;
  100.19 +        if (y>127) y=127;
  100.20 +        if (x<-128) x=-128;
  100.21 +        if (y<-128) y=-128;
  100.22 +
  100.23 +        /*Use Microsoft format*/
  100.24 +        mousedat[0]=0x40;
  100.25 +        mousedat[0]|=(((y>>6)&3)<<2);
  100.26 +        mousedat[0]|=((x>>6)&3);
  100.27 +        if (b&1) mousedat[0]|=0x20;
  100.28 +        if (b&2) mousedat[0]|=0x10;
  100.29 +        mousedat[1]=x&0x3F;
  100.30 +        mousedat[2]=y&0x3F;
  100.31 +        
  100.32 +        if (!(serial.mctrl&0x10))
  100.33 +        {
  100.34 +                serial_write_fifo(mousedat[0]);
  100.35 +                serial_write_fifo(mousedat[1]);
  100.36 +                serial_write_fifo(mousedat[2]);
  100.37 +        }
  100.38 +}
  100.39 +
  100.40 +void mouse_serial_rcr()
  100.41 +{
  100.42 +        mousepos=-1;
  100.43 +        mousedelay=1000;
  100.44 +}
  100.45 +        
  100.46 +void mousecallback()
  100.47 +{
  100.48 +        if (mousepos == -1)
  100.49 +        {
  100.50 +                mousepos = 0;
  100.51 +                serial_fifo_read = serial_fifo_write = 0;
  100.52 +                serial.linestat &= ~1;
  100.53 +                serial_write_fifo('M');
  100.54 +        }
  100.55 +        else if (serial_fifo_read != serial_fifo_write)
  100.56 +        {
  100.57 +                serial.iir=4;
  100.58 +                serial.linestat|=1;
  100.59 +                if (serial.mctrl&8) picint(0x10);
  100.60 +        }
  100.61 +//        printf("Mouse callback\n");
  100.62 +}
  100.63 +
  100.64 +void mouse_serial_init()
  100.65 +{
  100.66 +        mouse_poll = mouse_serial_poll;
  100.67 +        serial_rcr = mouse_serial_rcr;
  100.68 +}
  100.69 +
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/src/mouse_serial.h	Sun Apr 21 14:54:35 2013 +0100
   101.3 @@ -0,0 +1,1 @@
   101.4 +void mouse_serial_init();
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/src/neat.c	Sun Apr 21 14:54:35 2013 +0100
   102.3 @@ -0,0 +1,68 @@
   102.4 +/*This is the chipset used in the AMI 286 clone model*/
   102.5 +#include "ibm.h"
   102.6 +#include "io.h"
   102.7 +#include "neat.h"
   102.8 +
   102.9 +static uint8_t neat_regs[256];
  102.10 +static int neat_index;
  102.11 +static int neat_emspage[4];
  102.12 +
  102.13 +void neat_write(uint16_t port, uint8_t val)
  102.14 +{
  102.15 +        switch (port)
  102.16 +        {
  102.17 +                case 0x22:
  102.18 +                neat_index = val;
  102.19 +                break;
  102.20 +                
  102.21 +                case 0x23:
  102.22 +                neat_regs[neat_index] = val;
  102.23 +                switch (neat_index)
  102.24 +                {
  102.25 +                        case 0x6E: /*EMS page extension*/
  102.26 +                        neat_emspage[3] = (neat_emspage[3] & 0x7F) | (( val       & 3) << 7);
  102.27 +                        neat_emspage[2] = (neat_emspage[2] & 0x7F) | (((val >> 2) & 3) << 7);
  102.28 +                        neat_emspage[1] = (neat_emspage[1] & 0x7F) | (((val >> 4) & 3) << 7);
  102.29 +                        neat_emspage[0] = (neat_emspage[0] & 0x7F) | (((val >> 6) & 3) << 7);
  102.30 +                        break;
  102.31 +                }
  102.32 +                break;
  102.33 +
  102.34 +                case 0x0208: case 0x0209: case 0x4208: case 0x4209:
  102.35 +                case 0x8208: case 0x8209: case 0xC208: case 0xC209:
  102.36 +                neat_emspage[port >> 14] = (neat_emspage[port >> 14] & 0x180) | (val & 0x7F);                
  102.37 +                break;
  102.38 +        }
  102.39 +}
  102.40 +
  102.41 +uint8_t neat_read(uint16_t port)
  102.42 +{
  102.43 +        switch (port)
  102.44 +        {
  102.45 +                case 0x22:
  102.46 +                return neat_index;
  102.47 +                
  102.48 +                case 0x23:
  102.49 +                return neat_regs[neat_index];
  102.50 +        }
  102.51 +        return 0xff;
  102.52 +}
  102.53 +
  102.54 +void neat_writeems(uint32_t addr, uint8_t val)
  102.55 +{
  102.56 +        ram[(neat_emspage[(addr >> 14) & 3] << 14) + (addr & 0x3FFF)] = val;
  102.57 +}
  102.58 +
  102.59 +uint8_t neat_readems(uint32_t addr)
  102.60 +{
  102.61 +        return ram[(neat_emspage[(addr >> 14) & 3] << 14) + (addr & 0x3FFF)];
  102.62 +}
  102.63 +
  102.64 +void neat_init()
  102.65 +{
  102.66 +        io_sethandler(0x0022, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL);
  102.67 +        io_sethandler(0x0208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL);
  102.68 +        io_sethandler(0x4208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL);
  102.69 +        io_sethandler(0x8208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL);
  102.70 +        io_sethandler(0xc208, 0x0002, neat_read, NULL, NULL, neat_write, NULL, NULL);
  102.71 +}
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/src/neat.h	Sun Apr 21 14:54:35 2013 +0100
   103.3 @@ -0,0 +1,1 @@
   103.4 +void neat_init();
   104.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   104.2 +++ b/src/nvr.c	Sun Apr 21 14:54:35 2013 +0100
   104.3 @@ -0,0 +1,204 @@
   104.4 +#include <stdio.h>
   104.5 +#include <windows.h>
   104.6 +#include "ibm.h"
   104.7 +#include "nvr.h"
   104.8 +
   104.9 +int oldromset;
  104.10 +int nvrmask=63;
  104.11 +uint8_t nvrram[128];
  104.12 +int nvraddr;
  104.13 +
  104.14 +SYSTEMTIME systemtime;
  104.15 +
  104.16 +void getnvrtime()
  104.17 +{
  104.18 +        int c,d;
  104.19 +        uint8_t baknvr[10];
  104.20 +//        memset(nvrram,0,10);
  104.21 +//        return;
  104.22 +        memcpy(baknvr,nvrram,10);
  104.23 +        GetLocalTime(&systemtime);
  104.24 +        d=systemtime.wSecond%10;
  104.25 +        c=systemtime.wSecond/10;
  104.26 +        nvrram[0]=d|(c<<4);
  104.27 +        d=systemtime.wMinute%10;
  104.28 +        c=systemtime.wMinute/10;
  104.29 +        nvrram[2]=d|(c<<4);
  104.30 +        d=systemtime.wHour%10;
  104.31 +        c=systemtime.wHour/10;
  104.32 +        nvrram[4]=d|(c<<4);
  104.33 +        d=systemtime.wDayOfWeek%10;
  104.34 +        c=systemtime.wDayOfWeek/10;
  104.35 +        nvrram[6]=d|(c<<4);
  104.36 +        d=systemtime.wDay%10;
  104.37 +        c=systemtime.wDay/10;
  104.38 +        nvrram[7]=d|(c<<4);
  104.39 +        d=systemtime.wMonth%10;
  104.40 +        c=systemtime.wMonth/10;
  104.41 +        nvrram[8]=d|(c<<4);
  104.42 +        d=systemtime.wYear%10;
  104.43 +        c=(systemtime.wYear/10)%10;
  104.44 +        nvrram[9]=d|(c<<4);
  104.45 +        if (baknvr[0]!=nvrram[0] ||
  104.46 +            baknvr[2]!=nvrram[2] ||
  104.47 +            baknvr[4]!=nvrram[4] ||
  104.48 +            baknvr[6]!=nvrram[6] ||
  104.49 +            baknvr[7]!=nvrram[7] ||
  104.50 +            baknvr[8]!=nvrram[8] ||
  104.51 +            baknvr[9]!=nvrram[9]) nvrram[0xA]|=0x80;
  104.52 +}
  104.53 +
  104.54 +void nvr_recalc()
  104.55 +{
  104.56 +        int c;
  104.57 +        float newrtctime;
  104.58 +        c=1<<((nvrram[0xA]&0xF)-1);
  104.59 +        newrtctime=RTCCONST*(float)c;
  104.60 +        if (rtctime>newrtctime) rtctime=newrtctime;
  104.61 +}
  104.62 +
  104.63 +void nvr_rtc()
  104.64 +{
  104.65 +        int c;
  104.66 +        if (!(nvrram[0xA]&0xF))
  104.67 +        {
  104.68 +                rtctime=99999999;
  104.69 +                return;
  104.70 +        }
  104.71 +        c=1<<((nvrram[0xA]&0xF)-1);
  104.72 +        rtctime+=RTCCONST*(float)c;
  104.73 +//        pclog("RTCtime now %f\n",rtctime);
  104.74 +        nvrram[0xC]=0x40;
  104.75 +        if (nvrram[0xB]&0x40)
  104.76 +        {
  104.77 +                nvrram[0xC]|=0x80;
  104.78 +                if (AMSTRAD) picint(2);
  104.79 +                else         picint(0x100);
  104.80 +//                pclog("RTC int\n");
  104.81 +        }
  104.82 +}
  104.83 +
  104.84 +void writenvr(uint16_t addr, uint8_t val)
  104.85 +{
  104.86 +        int c;
  104.87 +//        printf("Write NVR %03X %02X %02X %04X:%04X %i\n",addr,nvraddr,val,cs>>4,pc,ins);
  104.88 +        if (addr&1)
  104.89 +        {
  104.90 +//                if (nvraddr == 0x33) pclog("NVRWRITE33 %02X %04X:%04X %i\n",val,CS,pc,ins);
  104.91 +                if (nvraddr >= 0xe && nvrram[nvraddr] != val) 
  104.92 +                   savenvr();
  104.93 +                if (nvraddr!=0xC && nvraddr!=0xD) nvrram[nvraddr]=val;
  104.94 +                
  104.95 +                if (nvraddr==0xA)
  104.96 +                {
  104.97 +//                        pclog("NVR rate %i\n",val&0xF);
  104.98 +                        if (val&0xF)
  104.99 +                        {
 104.100 +                                c=1<<((val&0xF)-1);
 104.101 +                                rtctime+=RTCCONST*(float)c;
 104.102 +                        }
 104.103 +                        else
 104.104 +                           rtctime=99999999;
 104.105 +                }
 104.106 +        }
 104.107 +        else        nvraddr=val&nvrmask;
 104.108 +}
 104.109 +
 104.110 +uint8_t readnvr(uint16_t addr)
 104.111 +{
 104.112 +        uint8_t temp;
 104.113 +//        printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
 104.114 +        if (addr&1)
 104.115 +        {
 104.116 +                if (nvraddr<=0xA) getnvrtime();
 104.117 +                if (nvraddr==0xD) nvrram[0xD]|=0x80;
 104.118 +                if (nvraddr==0xA)
 104.119 +                {
 104.120 +                        temp=nvrram[0xA];
 104.121 +                        nvrram[0xA]&=~0x80;
 104.122 +                        return temp;
 104.123 +                }
 104.124 +                if (nvraddr==0xC)
 104.125 +                {
 104.126 +                        if (AMSTRAD) picintc(2);
 104.127 +                        else         picintc(0x100);
 104.128 +                        temp=nvrram[0xC];
 104.129 +                        nvrram[0xC]=0;
 104.130 +                        return temp;
 104.131 +                }
 104.132 +//                if (AMIBIOS && nvraddr==0x36) return 0;
 104.133 +//                if (nvraddr==0xA) nvrram[0xA]^=0x80;
 104.134 +                return nvrram[nvraddr];
 104.135 +        }
 104.136 +        return nvraddr;
 104.137 +}
 104.138 +
 104.139 +void loadnvr()
 104.140 +{
 104.141 +        FILE *f;
 104.142 +        int c;
 104.143 +        nvrmask=63;
 104.144 +        oldromset=romset;
 104.145 +        switch (romset)
 104.146 +        {
 104.147 +                case ROM_PC1512:   f = romfopen("pc1512.nvr",  "rb"); break;
 104.148 +                case ROM_PC1640:   f = romfopen("pc1640.nvr",  "rb"); break;
 104.149 +                case ROM_PC200:    f = romfopen("pc200.nvr",   "rb"); break;
 104.150 +                case ROM_PC2086:   f = romfopen("pc2086.nvr",  "rb"); break;
 104.151 +                case ROM_PC3086:   f = romfopen("pc3086.nvr",  "rb"); break;                
 104.152 +                case ROM_IBMAT:    f = romfopen("at.nvr"    ,  "rb"); break;
 104.153 +                case ROM_CMDPC30:  f = romfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break;                
 104.154 +                case ROM_AMI286:   f = romfopen("ami286.nvr",  "rb"); nvrmask = 127; break;
 104.155 +                case ROM_DELL200:  f = romfopen("dell200.nvr", "rb"); nvrmask = 127; break;
 104.156 +                case ROM_IBMAT386: f = romfopen("at386.nvr"  , "rb"); nvrmask = 127; break;
 104.157 +                case ROM_ACER386:  f = romfopen("acer386.nvr", "rb"); nvrmask = 127; break;
 104.158 +                case ROM_MEGAPC:   f = romfopen("megapc.nvr",  "rb"); nvrmask = 127; break;
 104.159 +                case ROM_AMI386:   f = romfopen("ami386.nvr",  "rb"); nvrmask = 127; break;
 104.160 +                case ROM_AMI486:   f = romfopen("ami486.nvr",  "rb"); nvrmask = 127; break;
 104.161 +                case ROM_WIN486:   f = romfopen("win486.nvr",  "rb"); nvrmask = 127; break;
 104.162 +                case ROM_PCI486:   f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break;
 104.163 +                default: return;
 104.164 +        }
 104.165 +        if (!f)
 104.166 +        {
 104.167 +                memset(nvrram,0xFF,128);
 104.168 +                return;
 104.169 +        }
 104.170 +        fread(nvrram,128,1,f);
 104.171 +        fclose(f);
 104.172 +        nvrram[0xA]=6;
 104.173 +        nvrram[0xB]=0;
 104.174 +        c=1<<((6&0xF)-1);
 104.175 +        rtctime+=RTCCONST*(float)c;
 104.176 +}
 104.177 +void savenvr()
 104.178 +{
 104.179 +        FILE *f;
 104.180 +        switch (oldromset)
 104.181 +        {
 104.182 +                case ROM_PC1512:   f = romfopen("pc1512.nvr" , "wb"); break;
 104.183 +                case ROM_PC1640:   f = romfopen("pc1640.nvr" , "wb"); break;
 104.184 +                case ROM_PC200:    f = romfopen("pc200.nvr"  , "wb");  break;
 104.185 +                case ROM_PC2086:   f = romfopen("pc2086.nvr" , "wb"); break;
 104.186 +                case ROM_PC3086:   f = romfopen("pc3086.nvr" , "wb"); break;
 104.187 +                case ROM_IBMAT:    f = romfopen("at.nvr"     , "wb"); break;
 104.188 +                case ROM_CMDPC30:  f = romfopen("cmdpc30.nvr", "wb"); break;                
 104.189 +                case ROM_AMI286:   f = romfopen("ami286.nvr" , "wb"); break;
 104.190 +                case ROM_DELL200:  f = romfopen("dell200.nvr", "wb"); break;
 104.191 +                case ROM_IBMAT386: f = romfopen("at386.nvr"  , "wb"); break;
 104.192 +                case ROM_ACER386:  f = romfopen("acer386.nvr", "wb"); break;
 104.193 +                case ROM_MEGAPC:   f = romfopen("megapc.nvr" , "wb"); break;
 104.194 +                case ROM_AMI386:   f = romfopen("ami386.nvr" , "wb"); break;
 104.195 +                case ROM_AMI486:   f = romfopen("ami486.nvr" , "wb"); break;
 104.196 +                case ROM_WIN486:   f = romfopen("win486.nvr" , "wb"); break;
 104.197 +                case ROM_PCI486:   f = romfopen("hot-433.nvr", "wb"); break;                
 104.198 +                default: return;
 104.199 +        }
 104.200 +        fwrite(nvrram,128,1,f);
 104.201 +        fclose(f);
 104.202 +}
 104.203 +
 104.204 +void nvr_init()
 104.205 +{
 104.206 +        io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL);
 104.207 +}
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/src/nvr.h	Sun Apr 21 14:54:35 2013 +0100
   105.3 @@ -0,0 +1,1 @@
   105.4 +void nvr_init();
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/src/olivetti_m24.c	Sun Apr 21 14:54:35 2013 +0100
   106.3 @@ -0,0 +1,20 @@
   106.4 +#include "ibm.h"
   106.5 +#include "io.h"
   106.6 +#include "olivetti_m24.h"
   106.7 +
   106.8 +uint8_t olivetti_m24_read(uint16_t port)
   106.9 +{
  106.10 +        switch (port)
  106.11 +        {
  106.12 +                case 0x66:
  106.13 +                return 0x00;
  106.14 +                case 0x67:
  106.15 +                return 0x20 | 0x40 | 0x0C;
  106.16 +        }
  106.17 +        return 0xff;
  106.18 +}
  106.19 +
  106.20 +void olivetti_m24_init()
  106.21 +{
  106.22 +        io_sethandler(0x0066, 0x0002, olivetti_m24_read, NULL, NULL, NULL, NULL, NULL);
  106.23 +}
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/src/olivetti_m24.h	Sun Apr 21 14:54:35 2013 +0100
   107.3 @@ -0,0 +1,1 @@
   107.4 +void olivetti_m24_init();
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/src/opti.c	Sun Apr 21 14:54:35 2013 +0100
   108.3 @@ -0,0 +1,284 @@
   108.4 +/*OPTi 82C495 emulation
   108.5 +  This is the chipset used in the AMI386 model*/
   108.6 +#include "ibm.h"
   108.7 +
   108.8 +uint8_t optiregs[0x10];
   108.9 +int optireg;
  108.10 +
  108.11 +void writeopti(uint16_t addr, uint8_t val)
  108.12 +{
  108.13 +        switch (addr)
  108.14 +        {
  108.15 +                case 0x22:
  108.16 +                optireg=val;
  108.17 +                break;
  108.18 +                case 0x24:
  108.19 +                printf("Writing OPTI reg %02X %02X\n",optireg,val);
  108.20 +                if (optireg>=0x20 && optireg<=0x2C) optiregs[optireg-0x20]=val;
  108.21 +                break;
  108.22 +        }
  108.23 +}
  108.24 +
  108.25 +uint8_t readopti(uint16_t addr)
  108.26 +{
  108.27 +        switch (addr)
  108.28 +        {
  108.29 +                case 0x24:
  108.30 +                printf("Read OPTI reg %02X\n",optireg);
  108.31 +                if (optireg>=0x20 && optireg<=0x2C) return optiregs[optireg-0x20];
  108.32 +                break;
  108.33 +        }
  108.34 +        return 0xFF;
  108.35 +}
  108.36 +
  108.37 +/*Details for the chipset from Ralph Brown's interrupt list
  108.38 +  This describes the OPTi 82C493, the 82C495 seems similar except there is one
  108.39 +  more register (2C)
  108.40 +  
  108.41 +----------P00220024--------------------------
  108.42 +PORT 0022-0024 - OPTi 82C493 System Controller (SYSC) - CONFIGURATION REGISTERS
  108.43 +Desc:	The OPTi 486SXWB contains three chips and is designed for systems
  108.44 +	  running at 20, 25 and 33MHz.	The chipset includes an 82C493 System
  108.45 +	  Controller (SYSC), the 82C392 Data Buffer Controller, and the
  108.46 +	  82C206 Integrated peripheral Controller (IPC).
  108.47 +Note:	every access to PORT 0024h must be preceded by a write to PORT 0022h,
  108.48 +	  even if the same register is being accessed a second time
  108.49 +SeeAlso: PORT 0022h"82C206"
  108.50 +
  108.51 +0022  ?W  configuration register index (see #P0178)
  108.52 +0024  RW  configuration register data
  108.53 +
  108.54 +(Table P0178)
  108.55 +Values for OPTi 82C493 System Controller configuration register index:
  108.56 + 20h	Control Register 1 (see #P0179)
  108.57 + 21h	Control Register 2 (see #P0180)
  108.58 + 22h	Shadow RAM Control Register 1 (see #P0181)
  108.59 + 23h	Shadow RAM Control Register 2 (see #P0182)
  108.60 + 24h	DRAM Control Register 1 (see #P0183)
  108.61 + 25h	DRAM Control Register 2 (see #P0184)
  108.62 + 26h	Shadow RAM Control Register 3 (see #P0185)
  108.63 + 27h	Control Register 3 (see #P0186)
  108.64 + 28h	Non-cachable Block 1 Register 1 (see #P0187)
  108.65 + 29h	Non-cachable Block 1 Register 2 (see #P0188)
  108.66 + 2Ah	Non-cachable Block 2 Register 1 (see #P0187)
  108.67 + 2Bh	Non-cachable Block 2 Register 2 (see #P0188)
  108.68 +
  108.69 +Bitfields for OPTi-82C493 Control Register 1:
  108.70 +Bit(s)	Description	(Table P0179)
  108.71 + 7-6	Revision of 82C493 (readonly) (default=01)
  108.72 + 5	Burst wait state control
  108.73 +	1 = Secondary cache read hit cycle is 3-2-2-2 or 2-2-2-2
  108.74 +	0 = Secondary cache read hit cycle is 3-1-1-1 or 2-1-1-1 (default)
  108.75 +	(if bit 5 is set to 1, bit 4 must be set to 0)
  108.76 + 4	Cache memory data buffer output enable control
  108.77 +	0 = disable (default)
  108.78 +	1 = enable
  108.79 +	(must be disabled for frequency <= 33Mhz)
  108.80 + 3	Single Address Latch Enable (ALE)
  108.81 +	0 = disable (default)
  108.82 +	1 = enable
  108.83 +	(if enabled, SYSC will activate single ALE rather than multiples
  108.84 +	  during bus conversion cycles)
  108.85 + 2	enable Extra AT Cycle Wait State (default is 0 = disabled)
  108.86 + 1	Emulation keyboard Reset Control
  108.87 +	0 = disable (default)
  108.88 +	1 = enable
  108.89 +	Note:	This bit must be enabled in BIOS default value; enabling this
  108.90 +		  bit requires HALT instruction to be executed before SYSC
  108.91 +		  generates processor reset (CPURST)
  108.92 + 0	enable Alternative Fast Reset (default is 0 = disabled)
  108.93 +SeeAlso: #P0180,#P0186
  108.94 +
  108.95 +Bitfields for OPTi-82C493 Control Register 2:
  108.96 +Bit(s)	Description	(Table P0180)
  108.97 + 7	Master Mode Byte Swap Enable
  108.98 +	0 = disable (default)
  108.99 +	1 = enable
 108.100 + 6	Emulation Keyboard Reset Delay Control
 108.101 +	0 = Generate reset pulse 2us later (default)
 108.102 +	1 = Generate reset pulse immediately
 108.103 + 5	disable Parity Check (default is 0 = enabled)
 108.104 + 4	Cache Enable
 108.105 +	0 = Cache disabled and DRAM burst mode enabled (default)
 108.106 +	1 = Cache enabled and DRAM burst mode disabled
 108.107 + 3-2	Cache Size
 108.108 +	00  64KB (default)
 108.109 +	01  128KB
 108.110 +	10  256KB
 108.111 +	11  512KB
 108.112 + 1	Secondary Cache Read Burst Cycles Control
 108.113 +	0 = 3-1-1-1 cycle (default)
 108.114 +	1 = 2-1-1-1 cycle
 108.115 + 0	Cache Write Wait State Control
 108.116 +	0 = 1 wait state (default)
 108.117 +	1 = 0 wait state
 108.118 +SeeAlso: #P0179,#P0186
 108.119 +
 108.120 +Bitfields for OPTi-82C493 Shadow RAM Control Register 1:
 108.121 +Bit(s)	Description	(Table P0181)
 108.122 + 7	ROM(F0000h - FFFFFh) Enable
 108.123 +	0 = read/write on write-protected DRAM
 108.124 +	1 = read from ROM, write to DRAM (default)
 108.125 + 6	Shadow RAM at D0000h - EFFFFh Area
 108.126 +	0 = disable (default)
 108.127 +	1 = enable
 108.128 + 5	Shadow RAM at E0000h - EFFFFh Area
 108.129 +	0 = disable shadow RAM (default)
 108.130 +	    E0000h - EFFFFh ROM is defaulted to reside on XD bus
 108.131 +	1 = enable shadow RAM
 108.132 + 4	enable write-protect for Shadow RAM at D0000h - DFFFFh Area
 108.133 +	0 = disable (default)
 108.134 +	1 = enable
 108.135 + 3	enable write-protect for Shadow RAM at E0000h - EFFFFh Area
 108.136 +	0 = disable (default)
 108.137 +	1 = enable
 108.138 + 2	Hidden refresh enable (with holding CPU)
 108.139 +	(Hidden refresh must be disabled if 4Mx1 or 1M x4 bit DRAM are used)
 108.140 +	1 = disable (default)
 108.141 +	0 = enable
 108.142 + 1	unused
 108.143 + 0	enable Slow Refresh (four times slower than normal refresh)
 108.144 +	(default is 0 = disable)
 108.145 +SeeAlso: #P0182
 108.146 +
 108.147 +Bitfields for OPTi-82C493 Shadow RAM Control Register 2:
 108.148 +Bit(s)	Description	(Table P0182)
 108.149 + 7	enable Shadow RAM at EC000h - EFFFFh area
 108.150 + 6	enable Shadow RAM at E8000h - EBFFFh area
 108.151 + 5	enable Shadow RAM at E4000h - E7FFFh area
 108.152 + 4	enable Shadow RAM at E0000h - E3FFFh area
 108.153 + 3	enable Shadow RAM at DC000h - DFFFFh area
 108.154 + 2	enable Shadow RAM at D8000h - DBFFFh area
 108.155 + 1	enable Shadow RAM at D4000h - D7FFFh area
 108.156 + 0	enable Shadow RAM at D0000h - D3FFFh area
 108.157 +Note:	the default is disabled (0) for all areas
 108.158 +
 108.159 +Bitfields for OPTi-82C493 DRAM Control Register 1:
 108.160 +Bit(s)	Description	(Table P0183)
 108.161 + 7	DRAM size
 108.162 +	0 = 256K DRAM mode
 108.163 +	1 = 1M and 4M DRAM mode
 108.164 + 6-4	DRAM types used for bank0 and bank1
 108.165 +	bits 7-4  Bank0	  Bank1
 108.166 +	0000	  256K	     x
 108.167 +	0001	  256K	  256K
 108.168 +	0010	  256K	    1M
 108.169 +	0011	     x	     x
 108.170 +	01xx	     x	     x
 108.171 +	1000	    1M	     x	(default)
 108.172 +	1001	    1M	    1M
 108.173 +	1010	    1M	    4M
 108.174 +	1011	    4M	    1M
 108.175 +	1100	    4M	     x
 108.176 +	1101	    4M	    4M
 108.177 +	111x	     x	     x
 108.178 + 3	unused
 108.179 + 2-0	DRAM types used for bank2 and bank3
 108.180 +	bits 7,2-0  Bank2  Bank3
 108.181 +	x000	   1M	    x
 108.182 +	x001	   1M	   1M
 108.183 +	x010	    x	    x
 108.184 +	x011	   4M	   1M
 108.185 +	x100	   4M	    x
 108.186 +	x101	   4M	   4M
 108.187 +	x11x	    x	    x  (default)
 108.188 +SeeAlso: #P0184
 108.189 +
 108.190 +Bitfields for OPTi-82C493 DRAM Control Register 2:
 108.191 +Bit(s)	Description	(Table P0184)
 108.192 + 7-6	Read cycle additional wait states
 108.193 +	00 not used
 108.194 +	01 = 0
 108.195 +	10 = 1
 108.196 +	11 = 2 (default)
 108.197 + 5-4	Write cycle additional wait states
 108.198 +	00 = 0
 108.199 +	01 = 1
 108.200 +	10 = 2
 108.201 +	11 = 3 (default)
 108.202 + 3	Fast decode enable
 108.203 +	0 = disable fast decode. DRAM base wait states not changed (default)
 108.204 +	1 = enable fast decode. DRAM base wait state is decreased by 1
 108.205 +	Note:	This function may be enabled in 20/25Mhz operation to speed up
 108.206 +		  DRAM access.	If bit 4 of index register 21h (cache enable
 108.207 +		  bit) is enabled, this bit is automatically disabled--even if
 108.208 +		  set to 1
 108.209 + 2	unused
 108.210 + 1-0	ATCLK selection
 108.211 +	00  ATCLK = CLKI/6 (default)
 108.212 +	01  ATCLK = CLKI/4 (default)
 108.213 +	10  ATCLK = CLKI/3
 108.214 +	11  ATCLK = CLK2I/5  (CLKI * 2 /5)
 108.215 +	Note:	bit 0 will reflect the BCLKS (pin 142) status and bit 1 will be
 108.216 +		  set to 0 when 82C493 is reset.
 108.217 +SeeAlso: #P0183,#P0185
 108.218 +
 108.219 +Bitfields for OPTi-82C493 Shadow RAM Control Register 3:
 108.220 +Bit(s)	Description	(Table P0185)
 108.221 + 7	unused
 108.222 + 6	Shadow RAM copy enable for address C0000h - CFFFFh
 108.223 +	0 = Read/write at AT bus (default)
 108.224 +	1 = Read from AT bus and write into shadow RAM
 108.225 + 5	Shadow write protect at address C0000h - CFFFFh
 108.226 +	0 = Write protect disable (default)
 108.227 +	1 = Write protect enable
 108.228 + 4	enable Shadow RAM at C0000h - CFFFFh
 108.229 + 3	enable Shadow RAM at CC000h - CFFFFh
 108.230 + 2	enable Shadow RAM at C8000h - CBFFFh
 108.231 + 1	enable Shadow RAM at C4000h - C7FFFh
 108.232 + 0	enable Shadow RAM at C0000h - C3FFFh
 108.233 +Note:	the default is disabled (0) for bits 4-0
 108.234 +SeeAlso: #P0183,#P0184
 108.235 +
 108.236 +Bitfields for OPTi-82C493 Control Register 3:
 108.237 +Bit(s)	Description	(Table P0186)
 108.238 + 7	enable NCA# pin to low state (default is 1 = enabled)
 108.239 + 6-5	unused
 108.240 + 4	Video BIOS at C0000h - C8000h non-cacheable
 108.241 +	0 = cacheable
 108.242 +	1 = non-cacheable (default)
 108.243 + 3-0	Cacheable address range for local memory
 108.244 +	0000  0 - 64MB
 108.245 +	0001  0 - 4MB (default)
 108.246 +	0010  0 - 8MB
 108.247 +	0011  0 - 12MB
 108.248 +	0100  0 - 16MB
 108.249 +	0101  0 - 20MB
 108.250 +	0110  0 - 24MB
 108.251 +	0111  0 - 28MB
 108.252 +	1000  0 - 32MB
 108.253 +	1001  0 - 36MB
 108.254 +	1010  0 - 40MB
 108.255 +	1011  0 - 44MB
 108.256 +	1100  0 - 48MB
 108.257 +	1101  0 - 52MB
 108.258 +	1110  0 - 56MB
 108.259 +	1111  0 - 60MB
 108.260 +	Note:	If total memory is 1MB or 2MB the cacheable range is 0-1 MB or
 108.261 +		  0-2 MB and independent of the value of bits 3-0
 108.262 +SeeAlso: #P0179,#P0180
 108.263 +
 108.264 +Bitfields for OPTi-82C493 Non-cacheable Block Register 1:
 108.265 +Bit(s)	Description	(Table P0187)
 108.266 + 7-5	Size of non-cachable memory block
 108.267 +	000  64K
 108.268 +	001  128K
 108.269 +	010  256K
 108.270 +	011  512K
 108.271 +	1xx  disabled (default)
 108.272 + 4-2	unused
 108.273 + 1-0	Address bits 25 and 24 of non-cachable memory block (default = 00)
 108.274 +Note:	this register is used together with configuration register 29h
 108.275 +	  (non-cacheable block 1) or register 2Bh (block 2) (see #P0188) to
 108.276 +	  define a non-cacheable block.	 The starting address must be a
 108.277 +	  multiple of the block size
 108.278 +SeeAlso: #P0178,#P0188
 108.279 +
 108.280 +Bitfields for OPTi-82C493 Non-cacheable Block Register 2:
 108.281 +Bit(s)	Description	(Table P0188)
 108.282 + 7-0	Address bits 23-16 of non-cachable memory block (default = 0001xxxx)
 108.283 +Note:	the block address is forced to be a multiple of the block size by
 108.284 +	  ignoring the appropriate number of the least-significant bits
 108.285 +SeeAlso: #P0178,#P0187
 108.286 +
 108.287 +*/
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/src/pc.c	Sun Apr 21 14:54:35 2013 +0100
   109.3 @@ -0,0 +1,491 @@
   109.4 +#include <stdio.h>
   109.5 +#include <stdarg.h>
   109.6 +#include "ibm.h"
   109.7 +#include "video.h"
   109.8 +#include "amstrad.h"
   109.9 +#include "dma.h"
  109.10 +#include "mem.h"
  109.11 +#include "ide.h"
  109.12 +#include "mouse.h"
  109.13 +#include "pic.h"
  109.14 +#include "pit.h"
  109.15 +#include "serial.h"
  109.16 +#include "cdrom-ioctl.h"
  109.17 +#include "cpu.h"
  109.18 +#include "model.h"
  109.19 +#include "plat-mouse.h"
  109.20 +
  109.21 +int cdrom_enabled;
  109.22 +int CPUID;
  109.23 +int kb_win;
  109.24 +int vid_resize;
  109.25 +
  109.26 +int cycles_lost = 0;
  109.27 +
  109.28 +int clockrate;
  109.29 +int insc=0;
  109.30 +float mips,flops;
  109.31 +extern int mmuflush;
  109.32 +extern int readlnum,writelnum;
  109.33 +void fullspeed();
  109.34 +
  109.35 +int framecount,fps;
  109.36 +int pitsec;
  109.37 +int intcount;
  109.38 +int wakeups,wokeups;
  109.39 +int output;
  109.40 +int atfullspeed;
  109.41 +void loadconfig();
  109.42 +void saveconfig();
  109.43 +int infocus;
  109.44 +int mousecapture;
  109.45 +FILE *pclogf;
  109.46 +void pclog(const char *format, ...)
  109.47 +{
  109.48 +   char buf[256];
  109.49 +   return;
  109.50 +   if (!pclogf)
  109.51 +      pclogf=fopen("pclog.txt","wt");
  109.52 +//return;
  109.53 +   va_list ap;
  109.54 +   va_start(ap, format);
  109.55 +   vsprintf(buf, format, ap);
  109.56 +   va_end(ap);
  109.57 +   fputs(buf,pclogf);
  109.58 +fflush(pclogf);
  109.59 +}
  109.60 +
  109.61 +void fatal(const char *format, ...)
  109.62 +{
  109.63 +   char buf[256];
  109.64 +//   return;
  109.65 +   if (!pclogf)
  109.66 +      pclogf=fopen("pclog.txt","wt");
  109.67 +//return;
  109.68 +   va_list ap;
  109.69 +   va_start(ap, format);
  109.70 +   vsprintf(buf, format, ap);
  109.71 +   va_end(ap);
  109.72 +   fputs(buf,pclogf);
  109.73 +   fflush(pclogf);
  109.74 +   dumpregs();
  109.75 +   exit(-1);
  109.76 +}
  109.77 +
  109.78 +uint8_t cgastat;
  109.79 +int drawit=0;
  109.80 +
  109.81 +int pollmouse_delay = 2;
  109.82 +void pollmouse()
  109.83 +{
  109.84 +        int x,y;
  109.85 +        pollmouse_delay--;
  109.86 +        if (pollmouse_delay) return;
  109.87 +        pollmouse_delay = 2;
  109.88 +        poll_mouse();
  109.89 +        get_mouse_mickeys(&x,&y);
  109.90 +        if (mouse_poll)
  109.91 +           mouse_poll(x, y, mouse_b);
  109.92 +        if (mousecapture) position_mouse(64,64);
  109.93 +}
  109.94 +
  109.95 +/*PC1512 languages -
  109.96 +  7=English
  109.97 +  6=German
  109.98 +  5=French
  109.99 +  4=Spanish
 109.100 +  3=Danish
 109.101 +  2=Swedish
 109.102 +  1=Italian
 109.103 +        3,2,1 all cause the self test to fail for some reason
 109.104 +  */
 109.105 +
 109.106 +int cpuspeed2;
 109.107 +
 109.108 +int clocks[3][12][4]=
 109.109 +{
 109.110 +        {
 109.111 +                {4772728,13920,59660,5965},  /*4.77MHz*/
 109.112 +                {8000000,23333,110000,0}, /*8MHz*/
 109.113 +                {10000000,29166,137500,0}, /*10MHz*/
 109.114 +                {12000000,35000,165000,0}, /*12MHz*/
 109.115 +                {16000000,46666,220000,0}, /*16MHz*/
 109.116 +        },
 109.117 +        {
 109.118 +                {8000000,23333,110000,0}, /*8MHz*/
 109.119 +                {12000000,35000,165000,0}, /*12MHz*/
 109.120 +                {16000000,46666,220000,0}, /*16MHz*/
 109.121 +                {20000000,58333,275000,0}, /*20MHz*/
 109.122 +                {25000000,72916,343751,0}, /*25MHz*/
 109.123 +        },
 109.124 +        {
 109.125 +                {16000000, 46666,220000,0}, /*16MHz*/
 109.126 +                {20000000, 58333,275000,0}, /*20MHz*/
 109.127 +                {25000000, 72916,343751,0}, /*25MHz*/
 109.128 +                {33000000, 96000,454000,0}, /*33MHz*/
 109.129 +                {40000000,116666,550000,0}, /*40MHz*/
 109.130 +                {50000000, 72916*2,343751*2,0}, /*50MHz*/
 109.131 +                {33000000*2, 96000*2,454000*2,0}, /*66MHz*/
 109.132 +                {75000000, 72916*3,343751*3,0}, /*75MHz*/
 109.133 +                {80000000,116666*2,550000*2,0}, /*80MHz*/
 109.134 +                {100000000, 72916*4,343751*4,0}, /*100MHz*/
 109.135 +                {120000000,116666*3,550000*3,0}, /*120MHz*/
 109.136 +                {133000000, 96000*4,454000*4,0}, /*133MHz*/
 109.137 +        }
 109.138 +};
 109.139 +
 109.140 +int updatestatus;
 109.141 +int win_title_update=0;
 109.142 +
 109.143 +
 109.144 +void onesec()
 109.145 +{
 109.146 +        fps=framecount;
 109.147 +        framecount=0;
 109.148 +        win_title_update=1;
 109.149 +}
 109.150 +
 109.151 +void pc_reset()
 109.152 +{
 109.153 +        resetx86();
 109.154 +        cpu_set();
 109.155 +        dma_reset();
 109.156 +        fdc_reset();
 109.157 +        pic_reset();
 109.158 +        pit_reset();
 109.159 +        serial_reset();
 109.160 +
 109.161 +        setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
 109.162 +        
 109.163 +        adlib_reset();
 109.164 +        sb_reset();
 109.165 +
 109.166 +        ali1429_reset();
 109.167 +        et4000w32_reset();
 109.168 +        
 109.169 +//        video_init();
 109.170 +}
 109.171 +
 109.172 +void initpc()
 109.173 +{
 109.174 +        char *p;
 109.175 +//        allegro_init();
 109.176 +        get_executable_name(pcempath,511);
 109.177 +        pclog("executable_name = %s\n", pcempath);
 109.178 +        p=get_filename(pcempath);
 109.179 +        *p=0;
 109.180 +        pclog("path = %s\n", pcempath);        
 109.181 +
 109.182 +        keyboard_init();
 109.183 +        mouse_init();
 109.184 +        
 109.185 +        loadconfig();
 109.186 +        pclog("Config loaded\n");
 109.187 +        
 109.188 +        cpuspeed2=(AT)?2:1;
 109.189 +//        cpuspeed2=cpuspeed;
 109.190 +        atfullspeed=0;
 109.191 +        
 109.192 +        pclog("Initvideo\n");
 109.193 +        
 109.194 +        initvideo();
 109.195 +        mem_init();
 109.196 +        loadbios();
 109.197 +
 109.198 +        loaddisc(0,discfns[0]);
 109.199 +        loaddisc(1,discfns[1]);
 109.200 +        //loadfont();
 109.201 +        loadnvr();
 109.202 +        resetvideo();
 109.203 +        initsound();
 109.204 +        initpsg();
 109.205 +        inithdc();
 109.206 +        initega();
 109.207 +        initgus();
 109.208 +        resetide();
 109.209 +        ioctl_open(cdrom_drive);
 109.210 +        model_init();        
 109.211 +        video_init();
 109.212 +        adlib_init();
 109.213 +        sb_init();
 109.214 +        gus_init();
 109.215 +        
 109.216 +        pc_reset();
 109.217 +        
 109.218 +        pit_reset();        
 109.219 +        install_int_ex(onesec,BPS_TO_TIMER(1));
 109.220 +//        install_int_ex(vsyncint,BPS_TO_TIMER(60));
 109.221 +/*        if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed();
 109.222 +        mem_updatecache();
 109.223 +        ali1429_reset();
 109.224 +        et4000w32_reset();
 109.225 +//        CPUID=(is486 && (cpuspeed==7 || cpuspeed>=9));
 109.226 +//        pclog("Init - CPUID %i %i\n",CPUID,cpuspeed);
 109.227 +        shadowbios=0;
 109.228 +        
 109.229 +}
 109.230 +
 109.231 +void resetpc()
 109.232 +{
 109.233 +        pc_reset();
 109.234 +//        cpuspeed2=(AT)?2:1;
 109.235 +//        atfullspeed=0;
 109.236 +///*        if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed();
 109.237 +        shadowbios=0;
 109.238 +}
 109.239 +
 109.240 +void resetpchard()
 109.241 +{
 109.242 +        mem_resize();
 109.243 +        model_init();
 109.244 +        pclog("Video_init\n");
 109.245 +        video_init();
 109.246 +        adlib_init();
 109.247 +        sb_init();
 109.248 +        gus_init();
 109.249 +        
 109.250 +        pc_reset();
 109.251 +        
 109.252 +        resetide();
 109.253 +        
 109.254 +        loadnvr();
 109.255 +
 109.256 +//        cpuspeed2 = (AT)?2:1;
 109.257 +//        atfullspeed = 0;
 109.258 +//        setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
 109.259 +
 109.260 +        shadowbios = 0;
 109.261 +        ali1429_reset();
 109.262 +        
 109.263 +        keyboard_at_reset();
 109.264 +        
 109.265 +//        output=3;
 109.266 +}
 109.267 +
 109.268 +char romsets[17][40]={"IBM PC","IBM XT","Generic Turbo XT","Euro PC","Tandy 1000","Amstrad PC1512","Sinclair PC200","Amstrad PC1640","IBM AT","AMI 286 clone","Dell System 200","Misc 286","IBM AT 386","Misc 386","386 clone","486 clone","486 clone 2"};
 109.269 +char clockspeeds[3][12][16]=
 109.270 +{
 109.271 +        {"4.77MHz","8MHz","10MHz","12MHz","16MHz"},
 109.272 +        {"8MHz","12MHz","16MHz","20MHz","25MHz"},
 109.273 +        {"16MHz","20MHz","25MHz","33MHz","40MHz","50MHz","66MHz","75MHz","80MHz","100MHz","120MHz","133MHz"},
 109.274 +};
 109.275 +int framecountx=0;
 109.276 +int sndcount=0;
 109.277 +int oldat70hz;
 109.278 +
 109.279 +int sreadlnum,swritelnum,segareads,segawrites, scycles_lost;
 109.280 +
 109.281 +int serial_fifo_read, serial_fifo_write;
 109.282 +
 109.283 +int emu_fps = 0;
 109.284 +
 109.285 +void runpc()
 109.286 +{
 109.287 +        char s[200];
 109.288 +        int done=0;
 109.289 +        clockrate = models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed;
 109.290 +                if (is386)   exec386(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
 109.291 +                else if (AT) exec286(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
 109.292 +                else         execx86(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed / 100);
 109.293 +                keyboard_poll_host();
 109.294 +                keyboard_process();
 109.295 +//                checkkeys();
 109.296 +                pollmouse();
 109.297 +                framecountx++;
 109.298 +                framecount++;
 109.299 +                if (framecountx>=100)
 109.300 +                {
 109.301 +                        framecountx=0;
 109.302 +                        mips=(float)insc/1000000.0f;
 109.303 +                        insc=0;
 109.304 +                        flops=(float)fpucount/1000000.0f;
 109.305 +                        fpucount=0;
 109.306 +                        sreadlnum=readlnum;
 109.307 +                        swritelnum=writelnum;
 109.308 +                        segareads=egareads;
 109.309 +                        segawrites=egawrites;
 109.310 +                        scycles_lost = cycles_lost;
 109.311 +                        updatestatus=1;
 109.312 +                        readlnum=writelnum=0;
 109.313 +                        egareads=egawrites=0;
 109.314 +                        cycles_lost = 0;
 109.315 +                        mmuflush=0;
 109.316 +                        pitsec=0;
 109.317 +                        intcount=0;
 109.318 +                        wakeups=wokeups=0;
 109.319 +                        intcount=pitcount=0;
 109.320 +                        emu_fps = frames;
 109.321 +                        frames = 0;
 109.322 +                }
 109.323 +                if (win_title_update)
 109.324 +                {
 109.325 +                        win_title_update=0;
 109.326 +                        sprintf(s, "PCem v0.7 - %s - %s - %s - %i%%  %i %04X %i", model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : "Press CTRL-END to release mouse", fps, et4000w32p_getclock(), ECX, ins);
 109.327 +                        set_window_title(s);
 109.328 +                }
 109.329 +                done++;
 109.330 +/*                if ((at70hz && VGA)!=oldat70hz)
 109.331 +                {
 109.332 +                        oldat70hz=(at70hz && VGA);
 109.333 +                        if (oldat70hz) setrefresh(70); //install_int_ex(vsyncint,BPS_TO_TIMER(70));
 109.334 +                        else           setrefresh(60); //install_int_ex(vsyncint,BPS_TO_TIMER(60));
 109.335 +                        drawit=0;
 109.336 +                        done=0;
 109.337 +                }*/
 109.338 +//                printf("End of run!\n");
 109.339 +//        }
 109.340 +}
 109.341 +
 109.342 +void fullspeed()
 109.343 +{
 109.344 +        cpuspeed2=cpuspeed;
 109.345 +        if (!atfullspeed)
 109.346 +        {
 109.347 +                printf("Set fullspeed - %i %i %i\n",is386,AT,cpuspeed2);
 109.348 +                setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
 109.349 +//                if (is386) setpitclock(clocks[2][cpuspeed2][0]);
 109.350 +//                else       setpitclock(clocks[AT?1:0][cpuspeed2][0]);
 109.351 +        }
 109.352 +        atfullspeed=1;
 109.353 +        nvr_recalc();
 109.354 +}
 109.355 +
 109.356 +void speedchanged()
 109.357 +{
 109.358 +        if (atfullspeed)
 109.359 +        {
 109.360 +                cpuspeed2=cpuspeed;
 109.361 +                setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
 109.362 +//                if (is386) setpitclock(clocks[2][cpuspeed2][0]);
 109.363 +//                else       setpitclock(clocks[AT?1:0][cpuspeed2][0]);
 109.364 +        }
 109.365 +        mem_updatecache();
 109.366 +        nvr_recalc();
 109.367 +}
 109.368 +
 109.369 +void closepc()
 109.370 +{
 109.371 +        atapi->exit();
 109.372 +//        ioctl_close();
 109.373 +        dumpegaregs();
 109.374 +        dumppic();
 109.375 +        dumpgus();
 109.376 +//        output=7;
 109.377 +//        setpitclock(clocks[0][0][0]);
 109.378 +//        while (1) runpc();
 109.379 +        savedisc(0);
 109.380 +        savedisc(1);
 109.381 +        dumpregs();
 109.382 +        closevideo();
 109.383 +}
 109.384 +
 109.385 +/*int main()
 109.386 +{
 109.387 +        initpc();
 109.388 +        while (!key[KEY_F11])
 109.389 +        {
 109.390 +                runpc();
 109.391 +        }
 109.392 +        closepc();
 109.393 +        return 0;
 109.394 +}
 109.395 +
 109.396 +END_OF_MAIN();*/
 109.397 +
 109.398 +int cga_comp=0;
 109.399 +
 109.400 +void loadconfig()
 109.401 +{
 109.402 +        char s[512];
 109.403 +        char *p;
 109.404 +        append_filename(s,pcempath,"pcem.cfg",511);
 109.405 +        set_config_file(s);
 109.406 +        ADLIB=get_config_int(NULL,"adlib",1);
 109.407 +        GAMEBLASTER=get_config_int(NULL,"gameblaster",0);
 109.408 +        FASTDISC=get_config_int(NULL,"fast_disc",1);
 109.409 +        
 109.410 +        model = get_config_int(NULL, "model", 14);
 109.411 +        pclog("Model %i\n", model);
 109.412 +        romset = model_getromset();
 109.413 +        cpu_manufacturer = get_config_int(NULL, "cpu_manufacturer", 0);
 109.414 +        cpu = get_config_int(NULL, "cpu", 0);
 109.415 +        
 109.416 +        gfxcard=get_config_int(NULL,"gfxcard",0);
 109.417 +        video_speed = get_config_int(NULL, "video_speed", 3);
 109.418 +        sbtype=get_config_int(NULL,"sndcard",SB2);
 109.419 +        pclog("Model1 %i\n", model);
 109.420 +        p=(char *)get_config_string(NULL,"disc_a","");
 109.421 +        if (p) strcpy(discfns[0],p);
 109.422 +        else   strcpy(discfns[0],"");
 109.423 +        pclog("Model2 %i\n", model);        
 109.424 +        p=(char *)get_config_string(NULL,"disc_b","");
 109.425 +        if (p) strcpy(discfns[1],p);
 109.426 +        else   strcpy(discfns[1],"");
 109.427 +        pclog("Model3 %i\n", model);        
 109.428 +        mem_size=get_config_int(NULL,"mem_size",4);
 109.429 +        cdrom_drive=get_config_int(NULL,"cdrom_drive",0);
 109.430 +        cdrom_enabled=get_config_int(NULL,"cdrom_enabled",0);
 109.431 +        
 109.432 +        slowega=get_config_int(NULL,"slow_video",1);
 109.433 +        cache=get_config_int(NULL,"cache",3);
 109.434 +        cga_comp=get_config_int(NULL,"cga_composite",0);
 109.435 +        
 109.436 +        kb_win=get_config_int(NULL,"kb_win",0);
 109.437 +        vid_resize=get_config_int(NULL,"vid_resize",0);
 109.438 +//        cpuspeed=2;
 109.439 +
 109.440 +        hdc[0].spt=get_config_int(NULL,"hdc_sectors",0);
 109.441 +        hdc[0].hpc=get_config_int(NULL,"hdc_heads",0);
 109.442 +        hdc[0].tracks=get_config_int(NULL,"hdc_cylinders",0);
 109.443 +        p = (char *)get_config_string(NULL, "hdc_fn", "");
 109.444 +        if (p) strcpy(ide_fn[0], p);
 109.445 +        else   strcpy(ide_fn[0], "");
 109.446 +        hdc[1].spt=get_config_int(NULL,"hdd_sectors",0);
 109.447 +        hdc[1].hpc=get_config_int(NULL,"hdd_heads",0);
 109.448 +        hdc[1].tracks=get_config_int(NULL,"hdd_cylinders",0);
 109.449 +        p = (char *)get_config_string(NULL, "hdd_fn", "");
 109.450 +        if (p) strcpy(ide_fn[1], p);
 109.451 +        else   strcpy(ide_fn[1], "");
 109.452 +        pclog("Model4 %i\n", model);
 109.453 +}
 109.454 +
 109.455 +void saveconfig()
 109.456 +{
 109.457 +        pclog("saveconfig\n");
 109.458 +        config_new();
 109.459 +        pclog("config_new\n");
 109.460 +        set_config_int(NULL,"adlib",ADLIB);
 109.461 +        pclog("sci 1\n");
 109.462 +        set_config_int(NULL,"gameblaster",GAMEBLASTER);
 109.463 +        set_config_int(NULL,"fast_disc",FASTDISC);
 109.464 +        
 109.465 +        set_config_int(NULL, "model", model);
 109.466 +        set_config_int(NULL, "cpu_manufacturer", cpu_manufacturer);
 109.467 +        set_config_int(NULL, "cpu", cpu);
 109.468 +        
 109.469 +        set_config_int(NULL,"gfxcard",gfxcard);
 109.470 +        set_config_int(NULL,"video_speed", video_speed);
 109.471 +        set_config_int(NULL,"sndcard",sbtype);
 109.472 +        set_config_int(NULL,"cpu_speed",cpuspeed);
 109.473 +        set_config_int(NULL,"has_fpu",hasfpu);
 109.474 +        set_config_int(NULL,"slow_video",slowega);
 109.475 +        set_config_int(NULL,"cache",cache);
 109.476 +        set_config_int(NULL,"cga_composite",cga_comp);
 109.477 +        set_config_string(NULL,"disc_a",discfns[0]);
 109.478 +        set_config_string(NULL,"disc_b",discfns[1]);
 109.479 +        set_config_int(NULL,"mem_size",mem_size);
 109.480 +        set_config_int(NULL,"cdrom_drive",cdrom_drive);
 109.481 +        set_config_int(NULL,"cdrom_enabled",cdrom_enabled);
 109.482 +        set_config_int(NULL,"kb_win",kb_win);
 109.483 +        set_config_int(NULL,"vid_resize",vid_resize);
 109.484 +        
 109.485 +        set_config_int(NULL,"hdc_sectors",hdc[0].spt);
 109.486 +        set_config_int(NULL,"hdc_heads",hdc[0].hpc);
 109.487 +        set_config_int(NULL,"hdc_cylinders",hdc[0].tracks);
 109.488 +        set_config_string(NULL, "hdc_fn", ide_fn[0]);
 109.489 +        set_config_int(NULL,"hdd_sectors",hdc[1].spt);
 109.490 +        set_config_int(NULL,"hdd_heads",hdc[1].hpc);
 109.491 +        set_config_int(NULL,"hdd_cylinders",hdc[1].tracks);
 109.492 +        set_config_string(NULL, "hdd_fn", ide_fn[1]);
 109.493 +        pclog("saveconfig done\n");
 109.494 +}
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/src/pc.rc	Sun Apr 21 14:54:35 2013 +0100
   110.3 @@ -0,0 +1,158 @@
   110.4 +#include <windows.h>
   110.5 +#include "resources.h"
   110.6 +
   110.7 +MainMenu MENU DISCARDABLE
   110.8 +BEGIN
   110.9 +        POPUP "&File"
  110.10 +        BEGIN
  110.11 +                MENUITEM "&Hard Reset",           IDM_FILE_HRESET
  110.12 +                MENUITEM "E&xit",                 IDM_FILE_EXIT
  110.13 +        END
  110.14 +        POPUP "&Disc"
  110.15 +        BEGIN
  110.16 +                MENUITEM "Change drive &A:...", IDM_DISC_A
  110.17 +                MENUITEM "Change drive &B:...", IDM_DISC_B
  110.18 +                MENUITEM "&Eject drive A:",     IDM_EJECT_A
  110.19 +                MENUITEM "Eject drive B:",      IDM_EJECT_B
  110.20 +                MENUITEM "&Configure hard discs...",IDM_HDCONF
  110.21 +        END
  110.22 +        POPUP "&Settings"
  110.23 +        BEGIN
  110.24 +                MENUITEM "&Configure...", IDM_CONFIG
  110.25 +                POPUP "&CD-ROM"
  110.26 +                BEGIN
  110.27 +                        MENUITEM "&Disabled", IDM_CDROM_DISABLED
  110.28 +                        MENUITEM "&Empty",IDM_CDROM_EMPTY
  110.29 +                END
  110.30 +                POPUP "&Video"
  110.31 +                BEGIN
  110.32 +                        MENUITEM "&Resizeable window",IDM_VID_RESIZE
  110.33 +                END
  110.34 +        END
  110.35 +        POPUP "&Misc"
  110.36 +        BEGIN
  110.37 +                MENUITEM "&Status", IDM_STATUS
  110.38 +        END
  110.39 +END
  110.40 +
  110.41 +ConfigureDlg DIALOGEX 0, 0, 182, 240
  110.42 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
  110.43 +CAPTION "Configure PCem"
  110.44 +FONT 8, "MS Sans Serif"
  110.45 +BEGIN
  110.46 +    DEFPUSHBUTTON   "OK",IDOK,17,216,50,14, WS_TABSTOP
  110.47 +    PUSHBUTTON      "Cancel",IDCANCEL,71,216,50,14, WS_TABSTOP
  110.48 +    COMBOBOX        IDC_COMBO1,62,16,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.49 +    COMBOBOX        IDC_COMBO2,62,36,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.50 +    COMBOBOX        IDC_COMBOCPUM,62,56,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.51 +    COMBOBOX        IDC_COMBO3,62,76,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.52 +    COMBOBOX        IDC_COMBOCHC,62,96,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.53 +    COMBOBOX        IDC_COMBOSPD,62,116,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.54 +    COMBOBOX        IDC_COMBOSND,62,136,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.55 +    COMBOBOX        IDC_COMBOMEM,62,152,107,120,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
  110.56 +    CONTROL         "Game Blaster",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,172,118,10
  110.57 +    CONTROL         "Composite CGA",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,188,118,10
  110.58 +    LTEXT           "Machine :",IDC_STATIC,15,16,40,10
  110.59 +    LTEXT           "Video :",IDC_STATIC,15,36,34,10
  110.60 +    LTEXT           "CPU type :",IDC_STATIC,15,56,34,10
  110.61 +    LTEXT           "CPU :",IDC_STATIC,15,76,34,10
  110.62 +    LTEXT           "Cache :",IDC_STATIC,15,96,40,10
  110.63 +    LTEXT           "Video speed :",IDC_STATIC,15,116,40,10    
  110.64 +    LTEXT           "Soundcard :",IDC_STATIC,15,136,40,10
  110.65 +    LTEXT           "Memory :",IDC_STATIC,15,156,40,10
  110.66 +END
  110.67 +
  110.68 +HdConfDlg DIALOGEX 0, 0, 186, 172
  110.69 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
  110.70 +CAPTION "Configure Hard Discs"
  110.71 +FONT 8, "MS Sans Serif"
  110.72 +BEGIN
  110.73 +    DEFPUSHBUTTON   "OK",IDOK,31,152,50,14
  110.74 +    PUSHBUTTON      "Cancel",IDCANCEL,101,152,50,14
  110.75 +    
  110.76 +    LTEXT           "C:",IDC_STATIC,7,6,27,10
  110.77 +    EDITTEXT        IDC_EDITC, 7, 22, 136, 12, WS_DISABLED
  110.78 +    PUSHBUTTON      "...",IDC_CFILE,7 + 136,      22, 16, 14
  110.79 +    PUSHBUTTON      "New",IDC_CNEW,7 + 136 + 16, 22, 24, 14
  110.80 +    
  110.81 +    EDITTEXT        IDC_EDIT1,36,38,16,12, WS_DISABLED
  110.82 +    EDITTEXT        IDC_EDIT2,94,38,16,12, WS_DISABLED
  110.83 +    EDITTEXT        IDC_EDIT3,152,38,28,12, WS_DISABLED
  110.84 +    LTEXT           "Sectors:",IDC_STATIC,7,38,27,10
  110.85 +    LTEXT           "Heads:",IDC_STATIC,63,38,29,8
  110.86 +    LTEXT           "Cylinders:",IDC_STATIC,120,38,32,12
  110.87 +    LTEXT           "", IDC_TEXT1, 7, 54, 136, 12
  110.88 +    
  110.89 +    LTEXT           "D:",IDC_STATIC,7,76,27,10
  110.90 +    EDITTEXT        IDC_EDITD, 7, 92, 136, 12, WS_DISABLED
  110.91 +    PUSHBUTTON      "...",IDC_DFILE,7 + 136,     92, 16, 14
  110.92 +    PUSHBUTTON      "New",IDC_DNEW,7 + 136 + 16, 92, 24, 14
  110.93 +    
  110.94 +    EDITTEXT        IDC_EDIT4,36,108,16,12, WS_DISABLED
  110.95 +    EDITTEXT        IDC_EDIT5,94,108,16,12, WS_DISABLED
  110.96 +    EDITTEXT        IDC_EDIT6,152,108,28,12, WS_DISABLED
  110.97 +    LTEXT           "Sectors:",IDC_STATIC,7,108,27,10
  110.98 +    LTEXT           "Heads:",IDC_STATIC,63,108,29,8
  110.99 +    LTEXT           "Cylinders:",IDC_STATIC,120,108,32,12
 110.100 +    LTEXT           "", IDC_TEXT2, 7, 124, 136, 12    
 110.101 +    
 110.102 +END
 110.103 +
 110.104 +HdNewDlg DIALOGEX 0, 0, 186, 86
 110.105 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
 110.106 +CAPTION "New Hard Disc"
 110.107 +FONT 8, "MS Sans Serif"
 110.108 +BEGIN
 110.109 +    DEFPUSHBUTTON   "OK",IDOK,31,66,50,14
 110.110 +    PUSHBUTTON      "Cancel",IDCANCEL,101,66,50,14
 110.111 +    
 110.112 +    EDITTEXT        IDC_EDITC, 7, 6, 136, 12
 110.113 +    PUSHBUTTON      "...",IDC_CFILE,7 + 136,      6, 16, 14
 110.114 +    
 110.115 +    EDITTEXT        IDC_EDIT1,36,22,16,12
 110.116 +    EDITTEXT        IDC_EDIT2,94,22,16,12
 110.117 +    EDITTEXT        IDC_EDIT3,152,22,28,12
 110.118 +    LTEXT           "Sectors:",IDC_STATIC,7,22,27,10
 110.119 +    LTEXT           "Heads:",IDC_STATIC,63,22,29,8
 110.120 +    LTEXT           "Cylinders:",IDC_STATIC,120,22,32,12
 110.121 +    LTEXT           "", IDC_TEXT1, 7, 38, 136, 12
 110.122 +END
 110.123 +
 110.124 +HdSizeDlg DIALOGEX 0, 0, 186, 86
 110.125 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
 110.126 +CAPTION "Hard disc parameters"
 110.127 +FONT 8, "MS Sans Serif"
 110.128 +BEGIN
 110.129 +    DEFPUSHBUTTON   "OK",IDOK,31,66,50,14
 110.130 +    PUSHBUTTON      "Cancel",IDCANCEL,101,66,50,14
 110.131 +    
 110.132 +    LTEXT           "Initial settings are based on file size",IDC_STATIC,7,6,170,10
 110.133 +    
 110.134 +    EDITTEXT        IDC_EDIT1,36,22,16,12
 110.135 +    EDITTEXT        IDC_EDIT2,94,22,16,12
 110.136 +    EDITTEXT        IDC_EDIT3,152,22,28,12
 110.137 +    LTEXT           "Sectors:",IDC_STATIC,7,22,27,10
 110.138 +    LTEXT           "Heads:",IDC_STATIC,63,22,29,8
 110.139 +    LTEXT           "Cylinders:",IDC_STATIC,120,22,32,12
 110.140 +    LTEXT           "", IDC_TEXT1, 7, 38, 136, 12
 110.141 +END
 110.142 +
 110.143 +StatusDlg DIALOGEX 0,0,186,186
 110.144 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
 110.145 +CAPTION "Status"
 110.146 +FONT 8, "MS Sans Serif"
 110.147 +BEGIN
 110.148 +    LTEXT           "1",IDC_STEXT1,16,16,180,10
 110.149 +    LTEXT           "2",IDC_STEXT2,16,28,180,10
 110.150 +    LTEXT           "3",IDC_STEXT3,16,40,180,10
 110.151 +    LTEXT           "4",IDC_STEXT4,16,52,180,10
 110.152 +    LTEXT           "5",IDC_STEXT5,16,64,180,10
 110.153 +    LTEXT           "6",IDC_STEXT6,16,76,180,10
 110.154 +    LTEXT           "7",IDC_STEXT7,16,88,180,10
 110.155 +    LTEXT           "8",IDC_STEXT8,16,100,180,10
 110.156 +    LTEXT           "9",IDC_STEXT9,16,112,180,10
 110.157 +    LTEXT           "10",IDC_STEXT10,16,124,180,10
 110.158 +    LTEXT           "11",IDC_STEXT11,16,136,180,10
 110.159 +    LTEXT           "12",IDC_STEXT12,16,148,180,10
 110.160 +    LTEXT           "13",IDC_STEXT13,16,160,180,10
 110.161 +END
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/src/pci.c	Sun Apr 21 14:54:35 2013 +0100
   111.3 @@ -0,0 +1,99 @@
   111.4 +#include "ibm.h"
   111.5 +#include "io.h"
   111.6 +#include "mem.h"
   111.7 +
   111.8 +#include "pci.h"
   111.9 +
  111.10 +void    (*pci_card_write[32])(int func, int addr, uint8_t val);
  111.11 +uint8_t  (*pci_card_read[32])(int func, int addr);
  111.12 +static int pci_index, pci_func, pci_card, pci_bus, pci_enable;
  111.13 +static uint8_t card_16[256];
  111.14 +static uint8_t card_18[256];
  111.15 +
  111.16 +void pci_write(uint16_t port, uint8_t val)
  111.17 +{
  111.18 +        switch (port)
  111.19 +        {
  111.20 +                case 0xcf8:
  111.21 +                pci_index = val;
  111.22 +                break;
  111.23 +                case 0xcf9:
  111.24 +                pci_func = val & 7;
  111.25 +                pci_card = val >> 3;
  111.26 +                break;
  111.27 +                case 0xcfa:
  111.28 +                pci_bus = val;
  111.29 +                break;
  111.30 +                case 0xcfb:
  111.31 +                pci_enable = val & 0x80;
  111.32 +                break;
  111.33 +                
  111.34 +                case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
  111.35 +                if (!pci_enable) 
  111.36 +                   return;
  111.37 +                   
  111.38 +                pclog("PCI write bus %i card %i index %02X val %02X  %04X:%04X\n", pci_bus, pci_card, pci_index | (port & 3), val, CS, pc);
  111.39 +                
  111.40 +                if (!pci_bus && pci_card_write[pci_card])
  111.41 +                   pci_card_write[pci_card](pci_func, pci_index | (port & 3), val);
  111.42 +                
  111.43 +                break;
  111.44 +        }
  111.45 +}
  111.46 +
  111.47 +uint8_t pci_read(uint16_t port)
  111.48 +{
  111.49 +        switch (port)
  111.50 +        {
  111.51 +                case 0xcf8:
  111.52 +                return pci_index;
  111.53 +                case 0xcf9:
  111.54 +                return pci_card << 3;
  111.55 +                case 0xcfa:
  111.56 +                return pci_bus;
  111.57 +                case 0xcfb:
  111.58 +                return pci_enable;
  111.59 +                
  111.60 +                case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
  111.61 +                if (!pci_enable) 
  111.62 +                   return 0xff;
  111.63 +
  111.64 +                pclog("PCI read  bus %i card %i index %02X\n", pci_bus, pci_card, pci_index | (port & 3));
  111.65 +
  111.66 +                if (!pci_bus && pci_card_read[pci_card])
  111.67 +                   return pci_card_read[pci_card](pci_func, pci_index | (port & 3));
  111.68 +
  111.69 +                return 0xff;
  111.70 +        }
  111.71 +}
  111.72 +                
  111.73 +void pci_init()
  111.74 +{
  111.75 +        int c;
  111.76 +
  111.77 +        io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL);
  111.78 +        
  111.79 +        for (c = 0; c < 32; c++)
  111.80 +            pci_card_read[c] = pci_card_write[c] = NULL;
  111.81 +}
  111.82 +
  111.83 +void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val))
  111.84 +{
  111.85 +         pci_card_read[card] = read;
  111.86 +        pci_card_write[card] = write;
  111.87 +}
  111.88 +
  111.89 +void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val))
  111.90 +{
  111.91 +        int c;
  111.92 +        
  111.93 +        for (c = 0; c < 32; c++)
  111.94 +        {
  111.95 +                if (!pci_card_read[c] && !pci_card_write[c])
  111.96 +                {
  111.97 +                         pci_card_read[c] = read;
  111.98 +                        pci_card_write[c] = write;
  111.99 +                        return;
 111.100 +                }
 111.101 +        }
 111.102 +}
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/src/pci.h	Sun Apr 21 14:54:35 2013 +0100
   112.3 @@ -0,0 +1,3 @@
   112.4 +void pci_init();
   112.5 +void pci_add_specific(int card, uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val));
   112.6 +void pci_add(uint8_t (*read)(int func, int addr), void (*write)(int func, int addr, uint8_t val));
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/src/pic.c	Sun Apr 21 14:54:35 2013 +0100
   113.3 @@ -0,0 +1,313 @@
   113.4 +#include "ibm.h"
   113.5 +
   113.6 +int output;
   113.7 +int intclear;
   113.8 +int keywaiting=0;
   113.9 +int pit0;
  113.10 +int pic_intpending;
  113.11 +
  113.12 +void pic_updatepending()
  113.13 +{
  113.14 +        pic_intpending = (((pic.pend&~pic.mask)&~pic.mask2) || ((pic2.pend&~pic2.mask)&~pic2.mask2));
  113.15 +}
  113.16 +
  113.17 +
  113.18 +void pic_reset()
  113.19 +{
  113.20 +        pic.icw=0;
  113.21 +        pic.mask=0xFF;
  113.22 +        pic.mask2=0;
  113.23 +        pic.pend=pic.ins=0;
  113.24 +        pic.vector=8;
  113.25 +        pic.read=1;
  113.26 +        pic2.icw=0;
  113.27 +        pic2.mask=0xFF;
  113.28 +        pic.mask2=0;
  113.29 +        pic2.pend=pic2.ins=0;
  113.30 +        pic_intpending = 0;
  113.31 +}
  113.32 +
  113.33 +void pic_write(uint16_t addr, uint8_t val)
  113.34 +{
  113.35 +        int c;
  113.36 +//        pclog("Write PIC %04X %02X %04X(%06X):%04X\n",addr,val,CS,cs,pc);
  113.37 +        if (addr&1)
  113.38 +        {
  113.39 +                switch (pic.icw)
  113.40 +                {
  113.41 +                        case 0: /*OCW1*/
  113.42 +//                        printf("Write mask %02X %04X:%04X\n",val,CS,pc);
  113.43 +                        pic.mask=val;
  113.44 +                        pic_updatepending();
  113.45 +                        break;
  113.46 +                        case 1: /*ICW2*/
  113.47 +                        pic.vector=val&0xF8;
  113.48 +//                        printf("PIC vector now %02X\n",pic.vector);
  113.49 +           //             output=1;
  113.50 +                        if (pic.icw1&2) pic.icw=3;
  113.51 +                        else            pic.icw=2;
  113.52 +                        break;
  113.53 +                        case 2: /*ICW3*/
  113.54 +                        if (pic.icw1&1) pic.icw=3;
  113.55 +                        else            pic.icw=0;
  113.56 +                        break;
  113.57 +                        case 3: /*ICW4*/
  113.58 +                        pic.icw=0;
  113.59 +                        break;
  113.60 +                }
  113.61 +        }
  113.62 +        else
  113.63 +        {
  113.64 +                if (val&16) /*ICW1*/
  113.65 +                {
  113.66 +                        pic.mask=0xFF;
  113.67 +                        pic.mask2=0;
  113.68 +                        pic.icw=1;
  113.69 +                        pic.icw1=val;
  113.70 +                        pic_updatepending();
  113.71 +                }
  113.72 +                else if (!(val&8)) /*OCW2*/
  113.73 +                {
  113.74 +//                        printf("Clear ints - %02X %02X\n",pic.ins,val);
  113.75 +                        if ((val&0xE0)==0x60)
  113.76 +                        {
  113.77 +//                                pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7));
  113.78 +                                pic.ins&=~(1<<(val&7));
  113.79 +                                pic.mask2&=~(1<<(val&7));
  113.80 +//                                pic.pend&=(1<<(val&7));
  113.81 +//                                if ((val&7)==1) pollkeywaiting();
  113.82 +                                pic_updatepending();
  113.83 +                        }
  113.84 +                        else
  113.85 +                        {
  113.86 +                                for (c=0;c<8;c++)
  113.87 +                                {
  113.88 +                                        if (pic.ins&(1<<c))
  113.89 +                                        {
  113.90 +                                                pic.ins&=~(1<<c);
  113.91 +                                                pic.mask2&=~(1<<c);
  113.92 +//                                                pic.pend&=~(1<<c);
  113.93 +                                                if (c==0) pit0=1;
  113.94 +                                                if (c==1 && keywaiting)
  113.95 +                                                {
  113.96 +                                                        intclear&=~1;
  113.97 +//                                                        pollkeywaiting();
  113.98 +                                                }
  113.99 +                                                pic_updatepending();
 113.100 +//                                                pclog("Generic EOI - Cleared int %i\n",c);
 113.101 +                                                return;
 113.102 +                                        }
 113.103 +                                }
 113.104 +                        }
 113.105 +                }
 113.106 +                else               /*OCW3*/
 113.107 +                {
 113.108 +                       // if (val&4) fatal("PIC1 write OCW3 4 %02X\n",val);
 113.109 +                        if (val&2) pic.read=(val&1);
 113.110 +                        if (val&0x40) { } //fatal("PIC 1 write OCW3 40 %02X\n",val);
 113.111 +                }
 113.112 +        }
 113.113 +}
 113.114 +
 113.115 +uint8_t pic_read(uint16_t addr)
 113.116 +{
 113.117 +        if (addr&1) { /*pclog("Read PIC mask %02X\n",pic.mask);*/ return pic.mask; }
 113.118 +        if (pic.read) { /*pclog("Read PIC ins %02X\n",pic.ins);*/ return pic.ins; }
 113.119 +//        pclog("Read PIC pend %02X %08X\n",pic.pend,EDX);
 113.120 +        return pic.pend;
 113.121 +}
 113.122 +
 113.123 +void pic_init()
 113.124 +{
 113.125 +        io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL);
 113.126 +}
 113.127 +
 113.128 +void pic2_write(uint16_t addr, uint8_t val)
 113.129 +{
 113.130 +        int c;
 113.131 +//        pclog("Write PIC2 %04X %02X %04X:%04X %i\n",addr,val,CS,pc,ins);
 113.132 +        if (addr&1)
 113.133 +        {
 113.134 +                switch (pic2.icw)
 113.135 +                {
 113.136 +                        case 0: /*OCW1*/
 113.137 +//                        printf("PIC2 Write mask %02X %04X:%04X\n",val,CS,pc);
 113.138 +                        pic2.mask=val;
 113.139 +                        pic_updatepending();
 113.140 +                        break;
 113.141 +                        case 1: /*ICW2*/
 113.142 +                        pic2.vector=val&0xF8;
 113.143 +                        if (pic2.icw1&2) pic2.icw=3;
 113.144 +                        else            pic2.icw=2;
 113.145 +                        break;
 113.146 +                        case 2: /*ICW3*/
 113.147 +                        if (pic2.icw1&1) pic2.icw=3;
 113.148 +                        else            pic2.icw=0;
 113.149 +                        break;
 113.150 +                        case 3: /*ICW4*/
 113.151 +                        pic2.icw=0;
 113.152 +                        break;
 113.153 +                }
 113.154 +        }
 113.155 +        else
 113.156 +        {
 113.157 +                if (val&16) /*ICW1*/
 113.158 +                {
 113.159 +                        pic2.mask=0xFF;
 113.160 +                        pic2.mask2=0;
 113.161 +                        pic2.icw=1;
 113.162 +                        pic2.icw1=val;
 113.163 +                        pic_updatepending();
 113.164 +                }
 113.165 +                else if (!(val&8)) /*OCW2*/
 113.166 +                {
 113.167 +                        if ((val&0xE0)==0x60)
 113.168 +                        {
 113.169 +                                pic2.ins&=~(1<<(val&7));
 113.170 +                                pic2.mask2&=~(1<<(val&7));
 113.171 +                                pic_updatepending();
 113.172 +                        }
 113.173 +                        else
 113.174 +                        {
 113.175 +                                for (c=0;c<8;c++)
 113.176 +                                {
 113.177 +                                        if (pic2.ins&(1<<c))
 113.178 +                                        {
 113.179 +                                                pic2.ins&=~(1<<c);
 113.180 +                                                pic2.mask2&=~(1<<c);
 113.181 +                                                pic_updatepending();
 113.182 +                                                return;
 113.183 +                                        }
 113.184 +                                }
 113.185 +                        }
 113.186 +                }
 113.187 +                else               /*OCW3*/
 113.188 +                {
 113.189 +                        if (val&2) pic2.read=(val&1);
 113.190 +                }
 113.191 +        }
 113.192 +}
 113.193 +
 113.194 +uint8_t pic2_read(uint16_t addr)
 113.195 +{
 113.196 +        if (addr&1) { /*pclog("Read PIC2 mask %02X %04X:%08X\n",pic2.mask,CS,pc); */return pic2.mask; }
 113.197 +        if (pic2.read) { /*pclog("Read PIC2 ins %02X %04X:%08X\n",pic2.ins,CS,pc); */return pic2.ins; }
 113.198 +//        pclog("Read PIC2 pend %02X %04X:%08X\n",pic2.pend,CS,pc);
 113.199 +        return pic2.pend;
 113.200 +}
 113.201 +
 113.202 +void pic2_init()
 113.203 +{
 113.204 +        io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL);
 113.205 +}
 113.206 +
 113.207 +
 113.208 +void clearpic()
 113.209 +{
 113.210 +        pic.pend=pic.ins=0;
 113.211 +        pic_updatepending();
 113.212 +//        pclog("Clear PIC\n");
 113.213 +}
 113.214 +
 113.215 +int pic_current[16];
 113.216 +
 113.217 +void picint(uint16_t num)
 113.218 +{
 113.219 +//        if (num == 0x10) pclog("PICINT 10\n");
 113.220 +        if (num>0xFF)
 113.221 +        {
 113.222 +                pic2.pend|=(num>>8);
 113.223 +        }
 113.224 +        else
 113.225 +        {
 113.226 +                pic.pend|=num;
 113.227 +        }
 113.228 +        pic_updatepending();
 113.229 +}
 113.230 +
 113.231 +void picintlevel(uint16_t num)
 113.232 +{
 113.233 +        int c = 0;
 113.234 +        while (!(num & (1 << c))) c++;
 113.235 +//        pclog("INTLEVEL %04X %i\n", num, c);
 113.236 +        if (!pic_current[c])
 113.237 +        {
 113.238 +                pic_current[c]=1;
 113.239 +                if (num>0xFF)
 113.240 +                {
 113.241 +                        pic2.pend|=(num>>8);
 113.242 +                }
 113.243 +                else
 113.244 +                {
 113.245 +                        pic.pend|=num;
 113.246 +                }
 113.247 +        }
 113.248 +        pic_updatepending();
 113.249 +}
 113.250 +void picintc(uint16_t num)
 113.251 +{
 113.252 +        int c = 0;
 113.253 +        while (!(num & (1 << c))) c++;
 113.254 +//        pclog("INTC %04X %i\n", num, c);
 113.255 +        pic_current[c]=0;
 113.256 +        if (num>0xFF) pic2.pend&=~(num>>8);
 113.257 +        else
 113.258 +        {
 113.259 +                pic.pend&=~num;
 113.260 +        }
 113.261 +}
 113.262 +
 113.263 +uint8_t picinterrupt()
 113.264 +{
 113.265 +        uint8_t temp=pic.pend&~pic.mask;
 113.266 +        int c;
 113.267 +        for (c=0;c<8;c++)
 113.268 +        {
 113.269 +                if (temp&(1<<c))
 113.270 +                {
 113.271 +                        pic.pend&=~(1<<c);
 113.272 +                        pic.ins|=(1<<c);
 113.273 +                        pic.mask2|=(1<<c);
 113.274 +                        
 113.275 +                        pic_updatepending();
 113.276 +//                        if (!c) pclog("Taking timer int\n");
 113.277 +//                        if (c==5) printf("GUS IRQ!\n");
 113.278 +//                        if (c==1) printf("Keyboard int!\n");
 113.279 +//                        if (c==0) pic.ins&=~1;
 113.280 +                        return c+pic.vector;
 113.281 +                }
 113.282 +        }
 113.283 +        temp=pic2.pend&~pic2.mask;
 113.284 +        for (c=0;c<8;c++)
 113.285 +        {
 113.286 +                if (temp&(1<<c))
 113.287 +                {
 113.288 +                        pic2.pend&=~(1<<c);
 113.289 +                        pic2.ins|=(1<<c);
 113.290 +                        pic2.mask2|=(1<<c);
 113.291 +                        pic_updatepending();
 113.292 +//                        if (c==(14-8)) pclog("Taking IRQ 14 %02X\n",c+pic2.vector);
 113.293 +//                        printf("Taking high IRQ! %i\n",c);
 113.294 +//                        if (c==1) printf("Keyboard int!\n");
 113.295 +//                        if (c==0) pic.ins&=~1;
 113.296 +                        return c+pic2.vector;
 113.297 +                }
 113.298 +        }
 113.299 +        return 0xFF;
 113.300 +}
 113.301 +
 113.302 +void picclear(int num)
 113.303 +{
 113.304 +//        printf("Pic clear %02X\n",num);
 113.305 +        pic.pend&=~num;
 113.306 +        pic.ins&=~num;
 113.307 +        if (num==1) pit0=1;
 113.308 +        pic_updatepending();
 113.309 +}
 113.310 +
 113.311 +void dumppic()
 113.312 +{
 113.313 +        pclog("PIC1 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic.mask,pic.pend,pic.ins,pic.vector);
 113.314 +        pclog("PIC2 : MASK %02X PEND %02X INS %02X VECTOR %02X\n",pic2.mask,pic2.pend,pic2.ins,pic2.vector);
 113.315 +}
 113.316 +
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/src/pic.h	Sun Apr 21 14:54:35 2013 +0100
   114.3 @@ -0,0 +1,3 @@
   114.4 +void pic_init();
   114.5 +void pic2_init();
   114.6 +void pic_reset();
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/src/pit.c	Sun Apr 21 14:54:35 2013 +0100
   115.3 @@ -0,0 +1,305 @@
   115.4 +/*IBM AT -
   115.5 +  Write B0
   115.6 +  Write aa55
   115.7 +  Expects aa55 back*/
   115.8 +
   115.9 +#include <string.h>
  115.10 +#include "ibm.h"
  115.11 +#include "pit.h"
  115.12 +#include "video.h"
  115.13 +#include "cpu.h"
  115.14 +/*B0 to 40, two writes to 43, then two reads - value does not change!*/
  115.15 +/*B4 to 40, two writes to 43, then two reads - value _does_ change!*/
  115.16 +//Tyrian writes 4300 or 17512
  115.17 +int displine;
  115.18 +
  115.19 +int pitsec=0;
  115.20 +double PITCONST;
  115.21 +float cpuclock;
  115.22 +float isa_timing, bus_timing;
  115.23 +
  115.24 +int firsttime=1;
  115.25 +void setpitclock(float clock)
  115.26 +{
  115.27 +        float temp;
  115.28 +//        printf("PIT clock %f\n",clock);
  115.29 +        cpuclock=clock;
  115.30 +        PITCONST=clock/1193182.0;
  115.31 +        SPKCONST=clock/48000.0;
  115.32 +        CGACONST=(clock/(19687500.0/11.0));
  115.33 +        MDACONST=(clock/1813000.0);
  115.34 +        VGACONST1=(clock/25175000.0);
  115.35 +        VGACONST2=(clock/28322000.0);
  115.36 +        setsbclock(clock);
  115.37 +        SOUNDCONST=clock/200.0;
  115.38 +        CASCONST=PITCONST*1192;
  115.39 +        isa_timing = clock/8000000.0;
  115.40 +        bus_timing = clock/(double)cpu_busspeed;
  115.41 +        video_updatetiming();
  115.42 +//        pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock);
  115.43 +        GUSCONST=(clock/3125.0)/4.0;
  115.44 +        GUSCONST2=(clock/3125.0)/4.0; //Timer 2 at different rate to 1?
  115.45 +        video_recalctimings();
  115.46 +        RTCCONST=clock/32768.0;
  115.47 +}
  115.48 +
  115.49 +//#define PITCONST (8000000.0/1193000.0)
  115.50 +//#define PITCONST (cpuclock/1193000.0)
  115.51 +int pit0;
  115.52 +void pit_reset()
  115.53 +{
  115.54 +        memset(&pit,0,sizeof(PIT));
  115.55 +        pit.l[0]=0xFFFF; pit.c[0]=0xFFFF*PITCONST;
  115.56 +        pit.l[1]=0xFFFF; pit.c[1]=0xFFFF*PITCONST;
  115.57 +        pit.l[2]=0xFFFF; pit.c[2]=0xFFFF*PITCONST;
  115.58 +        pit.m[0]=pit.m[1]=pit.m[2]=0;
  115.59 +        pit.ctrls[0]=pit.ctrls[1]=pit.ctrls[2]=0;
  115.60 +        pit.thit[0]=1;
  115.61 +        spkstat=0;
  115.62 +}
  115.63 +
  115.64 +void clearpit()
  115.65 +{
  115.66 +        pit.c[0]=(pit.l[0]<<2);
  115.67 +}
  115.68 +
  115.69 +float pit_timer0_freq()
  115.70 +{
  115.71 +//        pclog("PIT timer 0 freq %04X %f %f\n",pit.l[0],(float)pit.l[0],1193182.0f/(float)pit.l[0]);
  115.72 +        return 1193182.0f/(float)pit.l[0];
  115.73 +}
  115.74 +extern int ins;
  115.75 +void pit_write(uint16_t addr, uint8_t val)
  115.76 +{
  115.77 +        int t;
  115.78 +        uint8_t oldctrl=pit.ctrl;
  115.79 +        cycles -= (int)PITCONST;
  115.80 +        pit0=1;
  115.81 +//        printf("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins);
  115.82 +        switch (addr&3)
  115.83 +        {
  115.84 +                case 3: /*CTRL*/
  115.85 +                if ((val&0xC0)==0xC0)
  115.86 +                {
  115.87 +                        if (!(val&0x20))
  115.88 +                        {
  115.89 +                                if (val&2) pit.rl[0]=pit.c[0]/PITCONST;
  115.90 +                                if (val&4) pit.rl[1]=pit.c[1]/PITCONST;
  115.91 +                                if (val&8) pit.rl[2]=pit.c[2]/PITCONST;
  115.92 +                        }
  115.93 +                        return;
  115.94 +                }
  115.95 +                pit.ctrls[val>>6]=pit.ctrl=val;
  115.96 +                if ((val>>7)==3)
  115.97 +                {
  115.98 +                        printf("Bad PIT reg select\n");
  115.99 +                        return;
 115.100 +//                        dumpregs();
 115.101 +//                        exit(-1);
 115.102 +                }
 115.103 +//                printf("CTRL write %02X\n",val);
 115.104 +                if (!(pit.ctrl&0x30))
 115.105 +                {
 115.106 +                        pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
 115.107 +                        if (pit.c[val>>6]<0) pit.rl[val>>6]=0;
 115.108 +//                        pclog("Timer latch %f %04X %04X\n",pit.c[0],pit.rl[0],pit.l[0]);
 115.109 +                        pit.ctrl|=0x30;
 115.110 +                        pit.rereadlatch[val>>6]=0;
 115.111 +                        pit.rm[val>>6]=3;
 115.112 +                }
 115.113 +                else
 115.114 +                {
 115.115 +                                pit.rm[val>>6]=pit.wm[val>>6]=(pit.ctrl>>4)&3;
 115.116 +                                pit.m[val>>6]=(val>>1)&7;
 115.117 +                                if (pit.m[val>>6]>5)
 115.118 +                                   pit.m[val>>6]&=3;
 115.119 +                                if (!(pit.rm[val>>6]))
 115.120 +                                {
 115.121 +                                        pit.rm[val>>6]=3;
 115.122 +                                        pit.rl[val>>6]=pit.c[val>>6]/PITCONST;
 115.123 +                                }
 115.124 +                                pit.rereadlatch[val>>6]=1;
 115.125 +                                if ((val>>6)==2) ppispeakon=speakon=(pit.m[2]==0)?0:1;
 115.126 +//                                pclog("ppispeakon %i\n",ppispeakon);
 115.127 +                }
 115.128 +                pit.wp=0;
 115.129 +                pit.thit[pit.ctrl>>6]=0;
 115.130 +                break;
 115.131 +                case 0: case 1: case 2: /*Timers*/
 115.132 +                t=addr&3;
 115.133 +//                if (t==2) ppispeakon=speakon=0;
 115.134 +//                pclog("Write timer %02X %i\n",pit.ctrls[t],pit.wm[t]);
 115.135 +                switch (pit.wm[t])
 115.136 +                {
 115.137 +                        case 1:
 115.138 +                        pit.l[t]=val;
 115.139 +                        pit.thit[t]=0;
 115.140 +                        pit.c[t]=pit.l[t]*PITCONST;
 115.141 +                        picintc(1);
 115.142 +                        break;
 115.143 +                        case 2:
 115.144 +                        pit.l[t]=(val<<8);
 115.145 +                        pit.thit[t]=0;
 115.146 +                        pit.c[t]=pit.l[t]*PITCONST;
 115.147 +                        picintc(1);
 115.148 +                        break;
 115.149 +                        case 0:
 115.150 +                        pit.l[t]&=0xFF;
 115.151 +                        pit.l[t]|=(val<<8);
 115.152 +                        pit.c[t]=pit.l[t]*PITCONST;
 115.153 +//                        pclog("%04X %f\n",pit.l[t],pit.c[t]);                        
 115.154 +                        pit.thit[t]=0;
 115.155 +                        pit.wm[t]=3;
 115.156 +                        picintc(1);
 115.157 +                        break;
 115.158 +                        case 3:
 115.159 +                        pit.l[t]&=0xFF00;
 115.160 +                        pit.l[t]|=val;
 115.161 +                        pit.wm[t]=0;
 115.162 +                        break;
 115.163 +/*
 115.164 +                        if (pit.wp)
 115.165 +                        {
 115.166 +                                pit.l[t]&=0xFF;
 115.167 +                                pit.l[t]|=(val<<8);
 115.168 +                                pit.c[t]=pit.l[t]*PITCONST;
 115.169 +                                pit.thit[t]=0;
 115.170 +                        }
 115.171 +                        else
 115.172 +                        {
 115.173 +                                pit.l[t]&=0xFF00;
 115.174 +                                pit.l[t]|=val;
 115.175 +                        }
 115.176 +                        pit.rl[t]=pit.l[t];
 115.177 +                        pit.wp^=1;
 115.178 +                        pit.rm[t]=3;
 115.179 +                                pit.rereadlatch[t]=1;
 115.180 +                        break;*/
 115.181 +                }
 115.182 +                speakval=(((float)pit.l[2]/(float)pit.l[0])*0x4000)-0x2000;
 115.183 +//                printf("Speakval now %i\n",speakval);
 115.184 +//                if (speakval>0x2000)
 115.185 +//                   printf("Speaker overflow - %i %i %04X %04X\n",pit.l[0],pit.l[2],pit.l[0],pit.l[2]);
 115.186 +                if (speakval>0x2000) speakval=0x2000;
 115.187 +                if (!pit.l[t])
 115.188 +                {
 115.189 +                        pit.l[t]|=0x10000;
 115.190 +                        pit.c[t]=pit.l[t]*PITCONST;
 115.191 +                }
 115.192 +                break;
 115.193 +        }
 115.194 +}
 115.195 +
 115.196 +uint8_t pit_read(uint16_t addr)
 115.197 +{
 115.198 +        uint8_t temp;
 115.199 +        cycles -= (int)PITCONST;        
 115.200 +//        printf("Read PIT %04X ",addr);
 115.201 +        switch (addr&3)
 115.202 +        {
 115.203 +                case 0: case 1: case 2: /*Timers*/
 115.204 +                if (pit.rereadlatch[addr&3])// || !(pit.ctrls[addr&3]&0x30))
 115.205 +                {
 115.206 +                        pit.rereadlatch[addr&3]=0;
 115.207 +                        pit.rl[addr&3]=pit.c[addr&3]/PITCONST;
 115.208 +                        if ((pit.c[addr&3]/PITCONST)>65536) pit.rl[addr&3]=0xFFFF;
 115.209 +                }
 115.210 +                switch (pit.rm[addr&3])
 115.211 +                {
 115.212 +                        case 0:
 115.213 +                        temp=pit.rl[addr&3]>>8;
 115.214 +                        pit.rm[addr&3]=3;
 115.215 +                        pit.rereadlatch[addr&3]=1;
 115.216 +                        break;
 115.217 +                        case 1:
 115.218 +                        temp=(pit.rl[addr&3])&0xFF;
 115.219 +                        pit.rereadlatch[addr&3]=1;
 115.220 +                        break;
 115.221 +                        case 2:
 115.222 +                        temp=(pit.rl[addr&3])>>8;
 115.223 +                        pit.rereadlatch[addr&3]=1;
 115.224 +                        break;
 115.225 +                        case 3:
 115.226 +                        temp=(pit.rl[addr&3])&0xFF;
 115.227 +                        if (pit.m[addr&3]&0x80) pit.m[addr&3]&=7;
 115.228 +                        else pit.rm[addr&3]=0;
 115.229 +                        break;
 115.230 +                }
 115.231 +                break;
 115.232 +                case 3: /*Control*/
 115.233 +                temp=pit.ctrl;
 115.234 +        }
 115.235 +//        printf("%02X %i %i %04X:%04X\n",temp,pit.rm[addr&3],pit.wp,cs>>4,pc);
 115.236 +        return temp;
 115.237 +}
 115.238 +
 115.239 +void pit_poll()
 115.240 +{
 115.241 +        pitsec++;
 115.242 +//                printf("Poll pit %f %f %f\n",pit.c[0],pit.c[1],pit.c[2]);
 115.243 +        if (pit.c[0]<1)
 115.244 +        {
 115.245 +                if (pit.m[0]==0 || pit.m[0]==4)
 115.246 +                {
 115.247 +//                        pit.c[0]&=0xFFFF;
 115.248 +                        pit.c[0]+=(0x10000*PITCONST);
 115.249 +                }
 115.250 +                else if (pit.m[0]==3 || pit.m[0]==2)
 115.251 +                {
 115.252 +                        if (pit.l[0]) pit.c[0]+=((float)(pit.l[0]*PITCONST));
 115.253 +                        else          pit.c[0]+=((float)(0x10000*PITCONST));
 115.254 +                }
 115.255 +//                pit.c[0]+=(pit.l[0]*PITCONST);
 115.256 +//                printf("PIT over! %f %i\n",pit.c[0],pit.m[0]);
 115.257 +                if (!pit.thit[0] && (pit.l[0]>0x14))
 115.258 +                {
 115.259 +//                        printf("PIT int!\n");
 115.260 +///                        printf("%05X %05X %02X\n",pit.c[0],pit.l[0],pit.ctrls[0]);
 115.261 +                        picint(1);
 115.262 +                }
 115.263 +                if (!pit.m[0] || pit.m[0]==4) pit.thit[0]=1;
 115.264 +//                if ((pit.ctrls[0]&0xE)==2) pit.thit[0]=1;
 115.265 +                pit0=0;
 115.266 +                pitcount++;
 115.267 +        }
 115.268 +        if (pit.c[1]<1)
 115.269 +        {
 115.270 + //               if (output) printf("PIT1 over %02X\n",pit.m[1]);
 115.271 +                if (pit.m[1]==0 || pit.m[1]==4)
 115.272 +                {
 115.273 +                        pit.c[1]=0xFFFFFF*PITCONST;
 115.274 +                }
 115.275 +                else
 115.276 +                {
 115.277 +                        pit.c[1]+=(pit.l[1]*PITCONST);
 115.278 +                }
 115.279 +//                if (output) pclog("%f %04X %02X\n",pit.c[1],pit.l[1],pit.ctrls[1]);
 115.280 +//                printf("DMA0!\n");
 115.281 +                readdma0();
 115.282 +        }
 115.283 +        if (pit.c[2]<1)
 115.284 +        {
 115.285 +//                printf("PIT 2 over %i\n",pit.m[2]);
 115.286 +                if (!pit.m[2] || pit.m[2]==4)
 115.287 +                {
 115.288 +                        pit.c[2]+=(0x10000*PITCONST);
 115.289 +                        speakon^=1;
 115.290 +                        ppispeakon^=1;
 115.291 +                }
 115.292 +                else
 115.293 +                {
 115.294 +                        pit.c[2]+=((pit.l[2]*PITCONST)/2);
 115.295 +                        if (pit.l[2]>0x30) /*Some games use very high frequencies as 'speaker off'. This stops them from generating noise*/
 115.296 +                           speakon^=1;
 115.297 +                        ppispeakon^=1;
 115.298 +//                        printf("Speakon %i %04X %i\n",speakon,pit.l[2],pit.c[2]);
 115.299 +                }
 115.300 +//                if (pit.ctrls[2]&0xE) pit.c[2]+=(pit.l[2]*PITCONST);
 115.301 +//                spkstat^=0x20;
 115.302 +        }
 115.303 +}
 115.304 +
 115.305 +void pit_init()
 115.306 +{
 115.307 +        io_sethandler(0x0040, 0x0004, pit_read, NULL, NULL, pit_write, NULL, NULL);
 115.308 +}
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/src/pit.h	Sun Apr 21 14:54:35 2013 +0100
   116.3 @@ -0,0 +1,3 @@
   116.4 +extern double PITCONST;
   116.5 +void pit_init();
   116.6 +void pit_reset();
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/src/plat-dinput.h	Sun Apr 21 14:54:35 2013 +0100
   117.3 @@ -0,0 +1,1 @@
   117.4 +extern LPDIRECTINPUT lpdi;
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/src/plat-keyboard.h	Sun Apr 21 14:54:35 2013 +0100
   118.3 @@ -0,0 +1,15 @@
   118.4 +#ifdef __cplusplus
   118.5 +extern "C" {
   118.6 +#endif
   118.7 +        void keyboard_init();
   118.8 +        void keyboard_close();
   118.9 +        void keyboard_poll_host();
  118.10 +        int key[256];
  118.11 +        
  118.12 +        #define KEY_LCONTROL 0x1d
  118.13 +        #define KEY_RCONTROL (0x1d | 0x80)
  118.14 +        #define KEY_END      (0x4f | 0x80)
  118.15 +#ifdef __cplusplus
  118.16 +}
  118.17 +#endif
  118.18 +
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/src/plat-mouse.h	Sun Apr 21 14:54:35 2013 +0100
   119.3 @@ -0,0 +1,13 @@
   119.4 +#ifdef __cplusplus
   119.5 +extern "C" {
   119.6 +#endif
   119.7 +        void mouse_init();
   119.8 +        void mouse_remove();
   119.9 +        extern int mouse_b;
  119.10 +        void poll_mouse();
  119.11 +        void position_mouse(int x, int y);
  119.12 +        void get_mouse_mickeys(int *x, int *y);
  119.13 +#ifdef __cplusplus
  119.14 +}
  119.15 +#endif
  119.16 +
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/src/ppi.c	Sun Apr 21 14:54:35 2013 +0100
   120.3 @@ -0,0 +1,19 @@
   120.4 +/*IBM 5150 cassette nonsense
   120.5 +  Calls F979 twice
   120.6 +  Expects CX to be nonzero, BX >$410 and <$540
   120.7 +    CX is loops between bit 4 of $62 changing
   120.8 +    BX is timer difference between calls
   120.9 +  */
  120.10 +
  120.11 +#include "ibm.h"
  120.12 +#include "pit.h"
  120.13 +
  120.14 +#include "plat-keyboard.h"
  120.15 +#include "plat-mouse.h"
  120.16 +
  120.17 +void ppi_reset()
  120.18 +{
  120.19 +        ppi.pa=0x0;//0x1D;
  120.20 +        ppi.pb=0x40;
  120.21 +}
  120.22 +
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/src/ppi.h	Sun Apr 21 14:54:35 2013 +0100
   121.3 @@ -0,0 +1,1 @@
   121.4 +extern int wasgated;
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/src/psg.c	Sun Apr 21 14:54:35 2013 +0100
   122.3 @@ -0,0 +1,206 @@
   122.4 +#include "ibm.h"
   122.5 +
   122.6 +float volslog[16]=
   122.7 +{
   122.8 +	0.00000f,0.59715f,0.75180f,0.94650f,
   122.9 +        1.19145f,1.50000f,1.88835f,2.37735f,
  122.10 +        2.99295f,3.76785f,4.74345f,5.97165f,
  122.11 +        7.51785f,9.46440f,11.9194f,15.0000f
  122.12 +};
  122.13 +
  122.14 +float psgcount[4],psglatch[4];
  122.15 +int psgstat[4];
  122.16 +int snlatch[4],sncount[4];
  122.17 +int snfreqlo[4],snfreqhi[4];
  122.18 +int snvol[4];
  122.19 +int curfreq[4];
  122.20 +uint32_t snshift[2]={0x8000,0x8000};
  122.21 +
  122.22 +#define SNCLOCK (2386360>>5)
  122.23 +uint8_t snnoise;
  122.24 +
  122.25 +void initpsg()
  122.26 +{
  122.27 +        int c;
  122.28 +        for (c=0;c<4;c++)
  122.29 +        {
  122.30 +                psgcount[c]=psglatch[c]=100000;
  122.31 +                psgstat[c]=0;
  122.32 +        }
  122.33 +}
  122.34 +
  122.35 +#define PSGCONST (32000.0/48000.0)
  122.36 +
  122.37 +void getpsg(signed short *p, int size)
  122.38 +{
  122.39 +//        printf("Getpsg %08X %i\n",p,size);
  122.40 +//        return;
  122.41 +        int c,d;
  122.42 +        for (c=0;c<size;c++)
  122.43 +        {
  122.44 +                p[c]=0;
  122.45 +                for (d=1;d<4;d++)
  122.46 +                {
  122.47 +                        if (psgstat[d]) p[c]+=volslog[snvol[d]]*170;
  122.48 +                        else            p[c]-=volslog[snvol[d]]*170;
  122.49 +                        psgcount[d]-=(512*PSGCONST);
  122.50 +                        while (psgcount[d]<=0.0 && psglatch[d]>1.0)
  122.51 +                        {
  122.52 +                                psgcount[d]+=psglatch[d];
  122.53 +                                psgstat[d]^=1;
  122.54 +                        }
  122.55 +                        if (psgcount[d]<=0.0) psgcount[d]=1.0;
  122.56 +                }
  122.57 +                d=(snnoise&4)?0:1;
  122.58 +                if (snshift[d]&1) p[c]+=volslog[snvol[0]]*170;
  122.59 +                psgcount[0]-=(512*PSGCONST);
  122.60 +                while (psgcount[0]<=0.0 && psglatch[0]>1.0)
  122.61 +                {
  122.62 +                        psgcount[0]+=psglatch[0];
  122.63 +                        snshift[1]>>=1;
  122.64 +                        if (!snshift[1]) snshift[1]=0x4000;
  122.65 +                        if ((snshift[0]&1)^((snshift[0]&4)?1:0)^((snshift[0]&0x8000)?1:0))
  122.66 +                           snshift[0]|=0x10000;
  122.67 +                        snshift[0]>>=1;
  122.68 +                }
  122.69 +                if (psgcount[0]<=0.0) psgcount[0]=1.0;
  122.70 +        }
  122.71 +}
  122.72 +
  122.73 +int lasttone;
  122.74 +uint8_t firstdat;
  122.75 +void writepsg(uint16_t addr, uint8_t data)
  122.76 +{
  122.77 +        int c;
  122.78 +        int freq;
  122.79 +        pclog("Write PSG %02X\n", data);
  122.80 +        if (data&0x80)
  122.81 +        {
  122.82 +                firstdat=data;
  122.83 +                switch (data&0x70)
  122.84 +                {
  122.85 +                        case 0:
  122.86 +                        snfreqlo[3]=data&0xF;
  122.87 +                        lasttone=3;
  122.88 +                        break;
  122.89 +                        case 0x10:
  122.90 +                        data&=0xF;
  122.91 +                        snvol[3]=0xF-data;
  122.92 +                        break;
  122.93 +                        case 0x20:
  122.94 +                        snfreqlo[2]=data&0xF;
  122.95 +                        lasttone=2;
  122.96 +                        break;
  122.97 +                        case 0x30:
  122.98 +                        data&=0xF;
  122.99 +                        snvol[2]=0xF-data;
 122.100 +                        break;
 122.101 +                        case 0x40:
 122.102 +                        snfreqlo[1]=data&0xF;
 122.103 +                        lasttone=1;
 122.104 +                        break;
 122.105 +                        case 0x50:
 122.106 +                        data&=0xF;
 122.107 +                        snvol[1]=0xF-data;
 122.108 +                        break;
 122.109 +                        case 0x60:
 122.110 +                        if ((data&3)!=(snnoise&3)) sncount[0]=0;
 122.111 +                        snnoise=data&0xF;
 122.112 +                        if ((data&3)==3)
 122.113 +                        {
 122.114 +                                curfreq[0]=curfreq[1]>>4;
 122.115 +                                snlatch[0]=snlatch[1];
 122.116 +                        }
 122.117 +                        else
 122.118 +                        {
 122.119 +                                switch (data&3)
 122.120 +                                {
 122.121 +                                        case 0:
 122.122 +                                        snlatch[0]=128<<7;
 122.123 +                                        curfreq[0]=SNCLOCK/256;
 122.124 +                                        snlatch[0]=0x400;
 122.125 +                                        sncount[0]=0;
 122.126 +                                        break;
 122.127 +                                        case 1:
 122.128 +                                        snlatch[0]=256<<7;
 122.129 +                                        curfreq[0]=SNCLOCK/512;
 122.130 +                                        snlatch[0]=0x800;
 122.131 +                                        sncount[0]=0;
 122.132 +                                        break;
 122.133 +                                        case 2:
 122.134 +                                        snlatch[0]=512<<7;
 122.135 +                                        curfreq[0]=SNCLOCK/1024;
 122.136 +                                        snlatch[0]=0x1000;
 122.137 +                                        sncount[0]=0;
 122.138 +                                        break;
 122.139 +                                        case 3:
 122.140 +                                        snlatch[0]=snlatch[1];
 122.141 +                                        sncount[0]=0;
 122.142 +                                }
 122.143 +                                if (snnoise&4) snlatch[0]<<=1;
 122.144 +                        }
 122.145 +                        break;
 122.146 +                        case 0x70:
 122.147 +                        data&=0xF;
 122.148 +                        snvol[0]=0xF-data;
 122.149 +                        break;
 122.150 +                }
 122.151 +        }
 122.152 +        else
 122.153 +        {
 122.154 +                if ((firstdat&0x70)==0x60)
 122.155 +                {
 122.156 +                        if ((data&3)!=(snnoise&3)) sncount[0]=0;
 122.157 +                        snnoise=data&0xF;
 122.158 +                        if ((data&3)==3)
 122.159 +                        {
 122.160 +                                curfreq[0]=curfreq[1]>>4;
 122.161 +                                snlatch[0]=snlatch[1];
 122.162 +//                                printf("SN 0 latch %04X\n",snlatch[0]);
 122.163 +                        }
 122.164 +                        else
 122.165 +                        {
 122.166 +                                switch (data&3)
 122.167 +                                {
 122.168 +                                        case 0:
 122.169 +                                        snlatch[0]=128<<7;
 122.170 +                                        curfreq[0]=SNCLOCK/256;
 122.171 +                                        snlatch[0]=0x400;
 122.172 +                                        sncount[0]=0;
 122.173 +                                        break;
 122.174 +                                        case 1:
 122.175 +                                        snlatch[0]=256<<7;
 122.176 +                                        curfreq[0]=SNCLOCK/512;
 122.177 +                                        snlatch[0]=0x800;
 122.178 +                                        sncount[0]=0;
 122.179 +                                        break;
 122.180 +                                        case 2:
 122.181 +                                        snlatch[0]=512<<7;
 122.182 +                                        curfreq[0]=SNCLOCK/1024;
 122.183 +                                        snlatch[0]=0x1000;
 122.184 +                                        sncount[0]=0;
 122.185 +                                        break;
 122.186 +                                        case 3:
 122.187 +                                        snlatch[0]=snlatch[1];
 122.188 +//                                        printf("SN 0 latch %04X\n",snlatch[0]);
 122.189 +                                        sncount[0]=0;
 122.190 +                                }
 122.191 +                                if (snnoise&4) snlatch[0]<<=1;
 122.192 +                        }
 122.193 +                        return;
 122.194 +                }
 122.195 +                else
 122.196 +                {
 122.197 +                        snfreqhi[lasttone]=data&0x3F;
 122.198 +                        freq=snfreqlo[lasttone]|(snfreqhi[lasttone]<<4);
 122.199 +                        snlatch[lasttone]=freq<<6;
 122.200 +                }
 122.201 +        }
 122.202 +        for (c=0;c<4;c++) psglatch[c]=(float)snlatch[c];
 122.203 +}
 122.204 +
 122.205 +void psg_init()
 122.206 +{
 122.207 +        pclog("psg_init\n");
 122.208 +        io_sethandler(0x00C0, 0x0001, NULL, NULL, NULL, writepsg, NULL, NULL);
 122.209 +}
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/src/psg.h	Sun Apr 21 14:54:35 2013 +0100
   123.3 @@ -0,0 +1,1 @@
   123.4 +void psg_init();
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/src/resources.h	Sun Apr 21 14:54:35 2013 +0100
   124.3 @@ -0,0 +1,62 @@
   124.4 +#define IDM_FILE_RESET  40000
   124.5 +#define IDM_FILE_HRESET 40001
   124.6 +#define IDM_FILE_EXIT   40002
   124.7 +#define IDM_DISC_A      40010
   124.8 +#define IDM_DISC_B      40011
   124.9 +#define IDM_EJECT_A     40012
  124.10 +#define IDM_EJECT_B     40013
  124.11 +#define IDM_HDCONF      40014
  124.12 +#define IDM_CONFIG      40020
  124.13 +#define IDM_STATUS      40030
  124.14 +#define IDM_KEY_ALLEGRO 40040
  124.15 +#define IDM_KEY_WINDOWS 40041
  124.16 +#define IDM_VID_RESIZE  40050
  124.17 +#define IDM_CDROM_EMPTY 40100
  124.18 +#define IDM_CDROM_REAL  40100
  124.19 +#define IDM_CDROM_DISABLED 40200
  124.20 +
  124.21 +#define IDC_COMBO1 1000
  124.22 +#define IDC_COMBO2 1001
  124.23 +#define IDC_COMBO3 1002
  124.24 +#define IDC_COMBO4 1003
  124.25 +#define IDC_COMBO5 1004
  124.26 +#define IDC_COMBO386 1005
  124.27 +#define IDC_COMBO486 1006
  124.28 +#define IDC_COMBOSND 1007
  124.29 +#define IDC_COMBOCHC 1008
  124.30 +#define IDC_COMBOMEM 1009
  124.31 +#define IDC_COMBOCPUM 1060
  124.32 +#define IDC_COMBOSPD  1061
  124.33 +#define IDC_CHECK1 1010
  124.34 +#define IDC_CHECK2 1011
  124.35 +#define IDC_CHECK3 1012
  124.36 +#define IDC_CHECK4 1013
  124.37 +#define IDC_STATIC 1020
  124.38 +#define IDC_EDIT1  1030
  124.39 +#define IDC_EDIT2  1031
  124.40 +#define IDC_EDIT3  1032
  124.41 +#define IDC_EDIT4  1033
  124.42 +#define IDC_EDIT5  1034
  124.43 +#define IDC_EDIT6  1035
  124.44 +#define IDC_TEXT1  1040
  124.45 +#define IDC_TEXT2  1041
  124.46 +#define IDC_EDITC  1050
  124.47 +#define IDC_CFILE  1051
  124.48 +#define IDC_CNEW   1052
  124.49 +#define IDC_EDITD  1053
  124.50 +#define IDC_DFILE  1054
  124.51 +#define IDC_DNEW   1055
  124.52 +
  124.53 +#define IDC_STEXT1 1100
  124.54 +#define IDC_STEXT2 1101
  124.55 +#define IDC_STEXT3 1102
  124.56 +#define IDC_STEXT4 1103
  124.57 +#define IDC_STEXT5 1104
  124.58 +#define IDC_STEXT6 1105
  124.59 +#define IDC_STEXT7 1106
  124.60 +#define IDC_STEXT8 1107
  124.61 +#define IDC_STEXT9 1108
  124.62 +#define IDC_STEXT10 1109
  124.63 +#define IDC_STEXT11 1110
  124.64 +#define IDC_STEXT12 1111
  124.65 +#define IDC_STEXT13 1112
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/src/sblaster.c	Sun Apr 21 14:54:35 2013 +0100
   125.3 @@ -0,0 +1,1104 @@
   125.4 +/*Jazz sample rates :
   125.5 +  386-33 - 12kHz
   125.6 +  486-33 - 20kHz
   125.7 +  486-50 - 32kHz
   125.8 +  Pentium - 45kHz*/
   125.9 +
  125.10 +#include <stdint.h>
  125.11 +#include <stdio.h>
  125.12 +#include "ibm.h"
  125.13 +#include "filters.h"
  125.14 +#include "io.h"
  125.15 +
  125.16 +static int sb_8_length,  sb_8_format,  sb_8_autoinit,  sb_8_pause,  sb_8_enable,  sb_8_autolen,  sb_8_output;
  125.17 +static int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
  125.18 +static int sb_pausetime = -1;
  125.19 +
  125.20 +static uint8_t sb_read_data[256];
  125.21 +static int sb_read_wp, sb_read_rp;
  125.22 +static int sb_speaker;
  125.23 +
  125.24 +static int sb_data_stat=-1;
  125.25 +
  125.26 +static int sb_irqnum = 7;
  125.27 +
  125.28 +static uint8_t sbe2;
  125.29 +static int sbe2count;
  125.30 +
  125.31 +static int sbe2dat[4][9] = {
  125.32 +  {  0x01, -0x02, -0x04,  0x08, -0x10,  0x20,  0x40, -0x80, -106 },
  125.33 +  { -0x01,  0x02, -0x04,  0x08,  0x10, -0x20,  0x40, -0x80,  165 },
  125.34 +  { -0x01,  0x02,  0x04, -0x08,  0x10, -0x20, -0x40,  0x80, -151 },
  125.35 +  {  0x01, -0x02,  0x04, -0x08, -0x10,  0x20, -0x40,  0x80,   90 }
  125.36 +};
  125.37 +
  125.38 +static uint8_t sb_data[8];
  125.39 +static int sb_commands[256]=
  125.40 +{
  125.41 +        -1,-1,-1,-1, 1, 2,-1, 0, 1,-1,-1,-1,-1,-1, 2, 1,
  125.42 +         1,-1,-1,-1, 2,-1, 2, 2,-1,-1,-1,-1, 0,-1,-1, 0,
  125.43 +         0,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1,-1,
  125.44 +        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  125.45 +         1, 2, 2,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1,
  125.46 +        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  125.47 +        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  125.48 +        -1,-1,-1,-1, 2, 2, 2, 2,-1,-1,-1,-1,-1, 0,-1, 0,
  125.49 +         2, 2,-1,-1,-1,-1,-1,-1, 2, 2,-1,-1,-1,-1,-1,-1,
  125.50 +         0,-1,-1,-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,
  125.51 +        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  125.52 +         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  125.53 +         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  125.54 +         0, 0,-1, 0, 0, 0, 0,-1, 0, 0, 0,-1,-1,-1,-1,-1,
  125.55 +         1, 0, 1, 0, 1,-1,-1, 0, 0,-1,-1,-1,-1,-1,-1,-1,
  125.56 +        -1,-1, 0,-1,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,-1, 0
  125.57 +};
  125.58 +
  125.59 +char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
  125.60 +uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405};
  125.61 +
  125.62 +/*These tables were 'borrowed' from DOSBox*/
  125.63 +	int8_t scaleMap4[64] = {
  125.64 +		0,  1,  2,  3,  4,  5,  6,  7,  0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,
  125.65 +		1,  3,  5,  7,  9, 11, 13, 15, -1,  -3,  -5,  -7,  -9, -11, -13, -15,
  125.66 +		2,  6, 10, 14, 18, 22, 26, 30, -2,  -6, -10, -14, -18, -22, -26, -30,
  125.67 +		4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
  125.68 +	};
  125.69 +	uint8_t adjustMap4[64] = {
  125.70 +		  0, 0, 0, 0, 0, 16, 16, 16,
  125.71 +		  0, 0, 0, 0, 0, 16, 16, 16,
  125.72 +		240, 0, 0, 0, 0, 16, 16, 16,
  125.73 +		240, 0, 0, 0, 0, 16, 16, 16,
  125.74 +		240, 0, 0, 0, 0, 16, 16, 16,
  125.75 +		240, 0, 0, 0, 0, 16, 16, 16,
  125.76 +		240, 0, 0, 0, 0,  0,  0,  0,
  125.77 +		240, 0, 0, 0, 0,  0,  0,  0
  125.78 +	};
  125.79 +
  125.80 +	int8_t scaleMap26[40] = {
  125.81 +		0,  1,  2,  3,  0,  -1,  -2,  -3,
  125.82 +		1,  3,  5,  7, -1,  -3,  -5,  -7,
  125.83 +		2,  6, 10, 14, -2,  -6, -10, -14,
  125.84 +		4, 12, 20, 28, -4, -12, -20, -28,
  125.85 +		5, 15, 25, 35, -5, -15, -25, -35
  125.86 +	};
  125.87 +	uint8_t adjustMap26[40] = {
  125.88 +		  0, 0, 0, 8,   0, 0, 0, 8,
  125.89 +		248, 0, 0, 8, 248, 0, 0, 8,
  125.90 +		248, 0, 0, 8, 248, 0, 0, 8,
  125.91 +		248, 0, 0, 8, 248, 0, 0, 8,
  125.92 +		248, 0, 0, 0, 248, 0, 0, 0
  125.93 +	};
  125.94 +
  125.95 +	int8_t scaleMap2[24] = {
  125.96 +		0,  1,  0,  -1, 1,  3,  -1,  -3,
  125.97 +		2,  6, -2,  -6, 4, 12,  -4, -12,
  125.98 +		8, 24, -8, -24, 6, 48, -16, -48
  125.99 +	};
 125.100 +	uint8_t adjustMap2[24] = {
 125.101 +		  0, 4,   0, 4,
 125.102 +		252, 4, 252, 4, 252, 4, 252, 4,
 125.103 +		252, 4, 252, 4, 252, 4, 252, 4,
 125.104 +		252, 0, 252, 0
 125.105 +	};
 125.106 +
 125.107 +
 125.108 +int sb_freq;
 125.109 +
 125.110 +int sbtype=0;
 125.111 +
 125.112 +int writebusy=0; /*Needed for Amnesia*/
 125.113 +
 125.114 +int16_t sbdatl=0,sbdatr=0;
 125.115 +int16_t sb16datl=0,sb16datr=0;
 125.116 +
 125.117 +int16_t sbdat;
 125.118 +uint8_t sbref;
 125.119 +int sbdacmode,sbdacpos,sbdat2;
 125.120 +int8_t sbstep;
 125.121 +int sbleftright=0;
 125.122 +int sbinput=0;
 125.123 +int sbreadstat,sbwritestat;
 125.124 +int sbreset;
 125.125 +uint8_t sbreaddat;
 125.126 +uint8_t sb_command,sbdata;
 125.127 +int sbcommandnext=1;
 125.128 +uint8_t sb_test;
 125.129 +int sb_timei,sb_timeo;
 125.130 +int sbcommandstat;
 125.131 +int sbhalted;
 125.132 +int adpcmstat=0;
 125.133 +int sbautolen;
 125.134 +int sbautoinit=0;
 125.135 +uint8_t sbcurcommand,sbdmacommand;
 125.136 +float SBCONST;
 125.137 +int sbstereo=0;
 125.138 +
 125.139 +int sbsamprate;
 125.140 +uint8_t sb_transfertype;
 125.141 +int sb_newtransfer;
 125.142 +int sb_dma16;
 125.143 +int sb_uart;
 125.144 +int sb_irq8,sb_irq16;
 125.145 +int sb_16_exit;
 125.146 +
 125.147 +uint8_t mixerindex;
 125.148 +uint8_t sb_mixer[256];
 125.149 +uint8_t sb_asp_regs[256];
 125.150 +
 125.151 +
 125.152 +int sb_att[]=
 125.153 +{
 125.154 +        310,368,437,520,618,735,873,1038,1234,1467,1743,2072,2463,2927,3479,
 125.155 +        4134,4914,5840,6941,8250,9805,11653,13850,16461,19564,23252,27635,32845,
 125.156 +        39036,46395,55140,65535
 125.157 +};
 125.158 +
 125.159 +void sb_irq(int irq8)
 125.160 +{
 125.161 +//        pclog("IRQ %i %02X\n",irq8,pic.mask);
 125.162 +        if (irq8) sb_irq8=1;
 125.163 +        else      sb_irq16=1;
 125.164 +        picint(1 << sb_irqnum);
 125.165 +}
 125.166 +void sb_irqc(int irq8)
 125.167 +{
 125.168 +        if (irq8) sb_irq8=0;
 125.169 +        else      sb_irq16=0;
 125.170 +        picintc(1 << sb_irqnum);
 125.171 +}
 125.172 +
 125.173 +void sb_mixer_set()
 125.174 +{
 125.175 +        if (sbtype==SB16)
 125.176 +        {
 125.177 +                mixer.master_l=sb_att[sb_mixer[0x30]>>3];
 125.178 +                mixer.master_r=sb_att[sb_mixer[0x31]>>3];
 125.179 +                mixer.voice_l =sb_att[sb_mixer[0x32]>>3];
 125.180 +                mixer.voice_r =sb_att[sb_mixer[0x33]>>3];
 125.181 +                mixer.fm_l    =sb_att[sb_mixer[0x34]>>3];
 125.182 +                mixer.fm_r    =sb_att[sb_mixer[0x35]>>3];
 125.183 +                mixer.bass_l  =sb_mixer[0x46]>>4;
 125.184 +                mixer.bass_r  =sb_mixer[0x47]>>4;
 125.185 +                mixer.treble_l=sb_mixer[0x44]>>4;
 125.186 +                mixer.treble_r=sb_mixer[0x45]>>4;
 125.187 +                mixer.filter=0;
 125.188 +                pclog("%02X %02X %02X %02X %02X %02X\n",sb_mixer[0x30],sb_mixer[0x31],sb_mixer[0x32],sb_mixer[0x33],sb_mixer[0x34],sb_mixer[0x35]);
 125.189 +                pclog("Mixer - %04X %04X %04X %04X %04X %04X\n",mixer.master_l,mixer.master_r,mixer.voice_l,mixer.voice_r,mixer.fm_l,mixer.fm_r);
 125.190 +        }
 125.191 +        else if (sbtype==SBPRO || sbtype==SBPRO2)
 125.192 +        {
 125.193 +                mixer.master_l=sb_att[(sb_mixer[0x22]>>4)|0x11];
 125.194 +                mixer.master_r=sb_att[(sb_mixer[0x22]&0xF)|0x11];
 125.195 +                mixer.voice_l =sb_att[(sb_mixer[0x04]>>4)|0x11];
 125.196 +                mixer.voice_r =sb_att[(sb_mixer[0x04]&0xF)|0x11];
 125.197 +                mixer.fm_l    =sb_att[(sb_mixer[0x26]>>4)|0x11];
 125.198 +                mixer.fm_r    =sb_att[(sb_mixer[0x26]&0xF)|0x11];
 125.199 +                mixer.filter  =!(sb_mixer[0xE]&0x20);
 125.200 +                mixer.bass_l  =mixer.bass_r  =8;
 125.201 +                mixer.treble_l=mixer.treble_r=8;
 125.202 +                pclog("%02X %02X %02X\n",sb_mixer[0x04],sb_mixer[0x22],sb_mixer[0x26]);
 125.203 +                pclog("Mixer - %04X %04X %04X %04X %04X %04X\n",mixer.master_l,mixer.master_r,mixer.voice_l,mixer.voice_r,mixer.fm_l,mixer.fm_r);
 125.204 +        }
 125.205 +        else
 125.206 +        {
 125.207 +                mixer.master_l=mixer.master_r=65535;
 125.208 +                mixer.voice_l =mixer.voice_r =65535;
 125.209 +                mixer.fm_l    =mixer.fm_r    =65535;
 125.210 +                mixer.bass_l  =mixer.bass_r  =8;
 125.211 +                mixer.treble_l=mixer.treble_r=8;
 125.212 +                mixer.filter=1;
 125.213 +        }
 125.214 +}
 125.215 +
 125.216 +void sb_mixer_reset()
 125.217 +{
 125.218 +        pclog("Mixer reset\n");
 125.219 +        if (sbtype==SB16)
 125.220 +        {
 125.221 +                sb_mixer[0x30]=31<<3;
 125.222 +                sb_mixer[0x31]=31<<3;
 125.223 +                sb_mixer[0x32]=31<<3;
 125.224 +                sb_mixer[0x33]=31<<3;
 125.225 +                sb_mixer[0x34]=31<<3;
 125.226 +                sb_mixer[0x35]=31<<3;
 125.227 +                sb_mixer[0x44]=8<<4;
 125.228 +                sb_mixer[0x45]=8<<4;
 125.229 +                sb_mixer[0x46]=8<<4;
 125.230 +                sb_mixer[0x47]=8<<4;
 125.231 +                sb_mixer[0x22]=(sb_mixer[0x30]&0xF0)|(sb_mixer[0x31]>>4);
 125.232 +                sb_mixer[0x04]=(sb_mixer[0x32]&0xF0)|(sb_mixer[0x33]>>4);
 125.233 +                sb_mixer[0x26]=(sb_mixer[0x34]&0xF0)|(sb_mixer[0x35]>>4);
 125.234 +        }
 125.235 +        if (sbtype==SBPRO || sbtype==SBPRO2)
 125.236 +        {
 125.237 +                sb_mixer[0x22]=0xFF;
 125.238 +                sb_mixer[0x04]=0xFF;
 125.239 +                sb_mixer[0x26]=0xFF;
 125.240 +                sb_mixer[0xE]=0;
 125.241 +        }
 125.242 +}
 125.243 +
 125.244 +void sb_dsp_reset()
 125.245 +{
 125.246 +        sbenable = sb_enable_i = 0;
 125.247 +        sb_command = 0;
 125.248 +        
 125.249 +        sb_uart = 0;
 125.250 +        sb_8_length = sbautolen = 0xFFFF;
 125.251 +
 125.252 +        sb_irqc(0);
 125.253 +        sb_irqc(1);
 125.254 +        sb_16_pause = 0;
 125.255 +        sb_read_wp = sb_read_rp = 0;
 125.256 +        sb_data_stat = -1;
 125.257 +        sb_speaker = 0;
 125.258 +        sb_pausetime = -1;
 125.259 +        sbe2 = 0xAA;
 125.260 +        sbe2count = 0;
 125.261 +
 125.262 +        sbreset = 0;
 125.263 +        sbenable = sb_enable_i = sb_count_i = 0;
 125.264 +        sbhalted = 0;
 125.265 +        sbdmacommand = 0;
 125.266 +        sbstereo = 0;
 125.267 +
 125.268 +        picintc(1 << sb_irqnum);
 125.269 +}
 125.270 +
 125.271 +void sb_reset()
 125.272 +{
 125.273 +        int c;
 125.274 +        
 125.275 +        sb_dsp_reset();
 125.276 +        sb_mixer_reset();
 125.277 +        sb_mixer_set();
 125.278 +        
 125.279 +        if (sbtype==SB16) sb_commands[8]=1;
 125.280 +        else              sb_commands[8]=-1;
 125.281 +        
 125.282 +        for (c = 0; c < 256; c++)
 125.283 +            sb_asp_regs[c] = 0;
 125.284 +        sb_asp_regs[5] = 0x01;
 125.285 +        sb_asp_regs[9] = 0xf8;
 125.286 +}
 125.287 +
 125.288 +void setsbclock(float clock)
 125.289 +{
 125.290 +        SBCONST=clock/1000000.0f;
 125.291 +        printf("SBCONST %f %f\n",SBCONST,clock);
 125.292 +        if (sb_timeo>255) sblatcho=(int)(SBCONST*(1000000.0f/(float)(sb_timeo-256)));
 125.293 +        else              sblatcho=SBCONST*(256-sb_timeo);
 125.294 +        if (sb_timei>255) sblatchi=(int)(SBCONST*(1000000.0f/(float)(sb_timei-256)));
 125.295 +        else              sblatchi=SBCONST*(256-sb_timei);
 125.296 +}
 125.297 +
 125.298 +void outmidi(uint8_t v)
 125.299 +{
 125.300 +        printf("Write MIDI %02X\n",v);
 125.301 +}
 125.302 +
 125.303 +void setsbtype(int type)
 125.304 +{
 125.305 +        sbtype=type;
 125.306 +        sbstereo=0;
 125.307 +        sb_mixer_set();
 125.308 +        if (sbtype==SB16) sb_commands[8]=1;
 125.309 +        else              sb_commands[8]=-1;
 125.310 +}
 125.311 +
 125.312 +
 125.313 +
 125.314 +
 125.315 +
 125.316 +
 125.317 +
 125.318 +void sb_add_data(uint8_t v)
 125.319 +{
 125.320 +        sb_read_data[sb_read_wp++]=v;
 125.321 +        sb_read_wp&=0xFF;
 125.322 +}
 125.323 +
 125.324 +#define ADPCM_4  1
 125.325 +#define ADPCM_26 2
 125.326 +#define ADPCM_2  3
 125.327 +
 125.328 +void sb_start_dma(int dma8, int autoinit, uint8_t format, int len)
 125.329 +{
 125.330 +        if (dma8)
 125.331 +        {
 125.332 +                sb_8_length=len;
 125.333 +                sb_8_format=format;
 125.334 +                sb_8_autoinit=autoinit;
 125.335 +                sb_8_pause=0;
 125.336 +                sb_8_enable=1;
 125.337 +                if (sb_16_enable && sb_16_output) sb_16_enable = 0;
 125.338 +                sb_8_output=1;
 125.339 +                sbenable=sb_8_enable;
 125.340 +                sbleftright=0;
 125.341 +                sbdacpos=0;
 125.342 +//                pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
 125.343 +        }
 125.344 +        else
 125.345 +        {
 125.346 +                sb_16_length=len;
 125.347 +                sb_16_format=format;
 125.348 +                sb_16_autoinit=autoinit;
 125.349 +                sb_16_pause=0;
 125.350 +                sb_16_enable=1;
 125.351 +                if (sb_8_enable && sb_8_output) sb_8_enable = 0;
 125.352 +                sb_16_output=1;
 125.353 +                sbenable=sb_16_enable;
 125.354 +//                pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len);
 125.355 +        }
 125.356 +}
 125.357 +
 125.358 +void sb_start_dma_i(int dma8, int autoinit, uint8_t format, int len)
 125.359 +{
 125.360 +        if (dma8)
 125.361 +        {
 125.362 +                sb_8_length=len;
 125.363 +                sb_8_format=format;
 125.364 +                sb_8_autoinit=autoinit;
 125.365 +                sb_8_pause=0;
 125.366 +                sb_8_enable=1;
 125.367 +                if (sb_16_enable && !sb_16_output) sb_16_enable = 0;                
 125.368 +                sb_8_output=0;
 125.369 +                sb_enable_i=sb_8_enable;
 125.370 +//                pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
 125.371 +        }
 125.372 +        else
 125.373 +        {
 125.374 +                sb_16_length=len;
 125.375 +                sb_16_format=format;
 125.376 +                sb_16_autoinit=autoinit;
 125.377 +                sb_16_pause=0;
 125.378 +                sb_16_enable=1;
 125.379 +                if (sb_8_enable && !sb_8_output) sb_8_enable = 0;                
 125.380 +                sb_16_output=0;
 125.381 +                sb_enable_i=sb_16_enable;
 125.382 +//                pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
 125.383 +        }
 125.384 +}
 125.385 +
 125.386 +uint8_t sb_8_read_dma()
 125.387 +{
 125.388 +        return readdma1();
 125.389 +}
 125.390 +void sb_8_write_dma(uint8_t val)
 125.391 +{
 125.392 +        writedma1(val);
 125.393 +}
 125.394 +uint16_t sb_16_read_dma()
 125.395 +{
 125.396 +        return readdma5();
 125.397 +}
 125.398 +void sb_16_write_dma(uint16_t val)
 125.399 +{
 125.400 +        writedma5(val);
 125.401 +}
 125.402 +
 125.403 +void sb_exec_command()
 125.404 +{
 125.405 +        int temp,c;
 125.406 +//        pclog("SB command %02X\n",sb_command);
 125.407 +        switch (sb_command)
 125.408 +        {
 125.409 +                case 0x10: /*8-bit direct mode*/
 125.410 +                sbdat=sbdatl=sbdatr=(sb_data[0]^0x80)<<8;
 125.411 +                break;
 125.412 +                case 0x14: /*8-bit single cycle DMA output*/
 125.413 +                sb_start_dma(1,0,0,sb_data[0]+(sb_data[1]<<8));
 125.414 +                break;
 125.415 +                case 0x17: /*2-bit ADPCM output with reference*/
 125.416 +                sbref=sb_8_read_dma();
 125.417 +                sbstep=0;
 125.418 +//                pclog("Ref byte 2 %02X\n",sbref);
 125.419 +                case 0x16: /*2-bit ADPCM output*/
 125.420 +                sb_start_dma(1,0,ADPCM_2,sb_data[0]+(sb_data[1]<<8));
 125.421 +                sbdat2=sb_8_read_dma();
 125.422 +                sb_8_length--;
 125.423 +                break;
 125.424 +                case 0x1C: /*8-bit autoinit DMA output*/
 125.425 +                if (sbtype<SB15) break;
 125.426 +                sb_start_dma(1,1,0,sb_8_autolen);
 125.427 +                break;
 125.428 +                case 0x1F: /*2-bit ADPCM autoinit output*/
 125.429 +                if (sbtype<SB15) break;
 125.430 +                sb_start_dma(1,1,ADPCM_2,sb_data[0]+(sb_data[1]<<8));
 125.431 +                sbdat2=sb_8_read_dma();
 125.432 +                sb_8_length--;
 125.433 +                break;
 125.434 +                case 0x20: /*8-bit direct input*/
 125.435 +                sb_add_data(0);
 125.436 +                break;
 125.437 +                case 0x24: /*8-bit single cycle DMA input*/
 125.438 +                sb_start_dma_i(1,0,0,sb_data[0]+(sb_data[1]<<8));
 125.439 +                break;
 125.440 +                case 0x2C: /*8-bit autoinit DMA input*/
 125.441 +                if (sbtype<SB15) break;
 125.442 +                sb_start_dma_i(1,1,0,sb_data[0]+(sb_data[1]<<8));
 125.443 +                break;
 125.444 +                case 0x40: /*Set time constant*/
 125.445 +                sb_timei=sb_timeo=sb_data[0];
 125.446 +                sblatcho=sblatchi=SBCONST*(256-sb_data[0]);
 125.447 +                temp=256-sb_data[0];
 125.448 +                temp=1000000/temp;
 125.449 +//                printf("Sample rate - %ihz (%i)\n",temp, sblatcho);
 125.450 +                sb_freq=temp;
 125.451 +                break;
 125.452 +                case 0x41: /*Set output sampling rate*/
 125.453 +                if (sbtype<SB16) break;
 125.454 +                sblatcho=(int)(SBCONST*(1000000.0f/(float)(sb_data[1]+(sb_data[0]<<8))));
 125.455 +//                printf("Sample rate - %ihz (%i)\n",sb_data[1]+(sb_data[0]<<8), sblatcho);
 125.456 +                sb_freq=sb_data[1]+(sb_data[0]<<8);
 125.457 +                sb_timeo=256+sb_freq;
 125.458 +                break;
 125.459 +                case 0x42: /*Set input sampling rate*/
 125.460 +                if (sbtype<SB16) break;
 125.461 +                sblatchi=(int)(SBCONST*(1000000.0f/(float)(sb_data[1]+(sb_data[0]<<8))));
 125.462 +//                printf("iample rate - %ihz\n",sb_data[1]+(sb_data[0]<<8));
 125.463 +                sb_timei=256+sb_data[1]+(sb_data[0]<<8);
 125.464 +                break;
 125.465 +                case 0x48: /*Set DSP block transfer size*/
 125.466 +                sb_8_autolen=sb_data[0]+(sb_data[1]<<8);
 125.467 +                break;
 125.468 +                case 0x75: /*4-bit ADPCM output with reference*/
 125.469 +                sbref=sb_8_read_dma();
 125.470 +                sbstep=0;
 125.471 +//                pclog("Ref byte 4 %02X\n",sbref);
 125.472 +                case 0x74: /*4-bit ADPCM output*/
 125.473 +                sb_start_dma(1,0,ADPCM_4,sb_data[0]+(sb_data[1]<<8));
 125.474 +                sbdat2=sb_8_read_dma();
 125.475 +                sb_8_length--;
 125.476 +                break;
 125.477 +                case 0x77: /*2.6-bit ADPCM output with reference*/
 125.478 +                sbref=sb_8_read_dma();
 125.479 +                sbstep=0;
 125.480 +//                pclog("Ref byte 26 %02X\n",sbref);
 125.481 +                case 0x76: /*2.6-bit ADPCM output*/
 125.482 +                sb_start_dma(1,0,ADPCM_26,sb_data[0]+(sb_data[1]<<8));
 125.483 +                sbdat2=sb_8_read_dma();
 125.484 +                sb_8_length--;
 125.485 +                break;
 125.486 +                case 0x7D: /*4-bit ADPCM autoinit output*/
 125.487 +                if (sbtype<SB15) break;
 125.488 +                sb_start_dma(1,1,ADPCM_4,sb_data[0]+(sb_data[1]<<8));
 125.489 +                sbdat2=sb_8_read_dma();
 125.490 +                sb_8_length--;
 125.491 +                break;
 125.492 +                case 0x7F: /*2.6-bit ADPCM autoinit output*/
 125.493 +                if (sbtype<SB15) break;
 125.494 +                sb_start_dma(1,1,ADPCM_26,sb_data[0]+(sb_data[1]<<8));
 125.495 +                sbdat2=sb_8_read_dma();
 125.496 +                sb_8_length--;
 125.497 +                break;
 125.498 +                case 0x80: /*Pause DAC*/
 125.499 +                sb_pausetime=sb_data[0]+(sb_data[1]<<8);
 125.500 +//                pclog("SB pause %04X\n",sb_pausetime);
 125.501 +                sbenable=1;
 125.502 +                break;
 125.503 +                case 0x90: /*High speed 8-bit autoinit DMA output*/
 125.504 +                if (sbtype<SB2) break;
 125.505 +                sb_start_dma(1,1,0,sb_8_autolen);
 125.506 +                break;
 125.507 +                case 0x91: /*High speed 8-bit single cycle DMA output*/
 125.508 +                if (sbtype<SB2) break;
 125.509 +                sb_start_dma(1,0,0,sb_8_autolen);
 125.510 +                break;
 125.511 +                case 0x98: /*High speed 8-bit autoinit DMA input*/
 125.512 +                if (sbtype<SB2) break;
 125.513 +                sb_start_dma_i(1,1,0,sb_8_autolen);
 125.514 +                break;
 125.515 +                case 0x99: /*High speed 8-bit single cycle DMA input*/
 125.516 +                if (sbtype<SB2) break;
 125.517 +                sb_start_dma_i(1,0,0,sb_8_autolen);
 125.518 +                break;
 125.519 +                case 0xA0: /*Set input mode to mono*/
 125.520 +                case 0xA8: /*Set input mode to stereo*/
 125.521 +                break;
 125.522 +                case 0xB0: case 0xB1: case 0xB2: case 0xB3:
 125.523 +                case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/
 125.524 +                if (sbtype<SB16) break;
 125.525 +                sb_start_dma(0,sb_command&4,sb_data[0],sb_data[1]+(sb_data[2]<<8));
 125.526 +                sb_16_autolen=sb_data[1]+(sb_data[2]<<8);
 125.527 +                break;
 125.528 +                case 0xB8: case 0xB9: case 0xBA: case 0xBB:
 125.529 +                case 0xBC: case 0xBD: case 0xBE: case 0xBF: /*16-bit DMA input*/
 125.530 +                if (sbtype<SB16) break;
 125.531 +                sb_start_dma_i(0,sb_command&4,sb_data[0],sb_data[1]+(sb_data[2]<<8));
 125.532 +                sb_16_autolen=sb_data[1]+(sb_data[2]<<8);
 125.533 +                break;
 125.534 +                case 0xC0: case 0xC1: case 0xC2: case 0xC3:
 125.535 +                case 0xC4: case 0xC5: case 0xC6: case 0xC7: /*8-bit DMA output*/
 125.536 +                if (sbtype<SB16) break;
 125.537 +                sb_start_dma(1,sb_command&4,sb_data[0],sb_data[1]+(sb_data[2]<<8));
 125.538 +                sb_8_autolen=sb_data[1]+(sb_data[2]<<8);
 125.539 +                break;
 125.540 +                case 0xC8: case 0xC9: case 0xCA: case 0xCB:
 125.541 +                case 0xCC: case 0xCD: case 0xCE: case 0xCF: /*8-bit DMA input*/
 125.542 +                if (sbtype<SB16) break;
 125.543 +                sb_start_dma_i(1,sb_command&4,sb_data[0],sb_data[1]+(sb_data[2]<<8));
 125.544 +                sb_8_autolen=sb_data[1]+(sb_data[2]<<8);
 125.545 +                break;
 125.546 +                case 0xD0: /*Pause 8-bit DMA*/
 125.547 +                sb_8_pause=1;
 125.548 +                break;
 125.549 +                case 0xD1: /*Speaker on*/
 125.550 +                sb_speaker=1;
 125.551 +                break;
 125.552 +                case 0xD3: /*Speaker off*/
 125.553 +                sb_speaker=0;
 125.554 +                break;
 125.555 +                case 0xD4: /*Continue 8-bit DMA*/
 125.556 +                sb_8_pause=0;
 125.557 +                break;
 125.558 +                case 0xD5: /*Pause 16-bit DMA*/
 125.559 +                if (sbtype<SB16) break;
 125.560 +                sb_16_pause=1;
 125.561 +                break;
 125.562 +                case 0xD6: /*Continue 16-bit DMA*/
 125.563 +                if (sbtype<SB16) break;
 125.564 +                sb_16_pause=0;
 125.565 +                break;
 125.566 +                case 0xD8: /*Get speaker status*/
 125.567 +                sb_add_data(sb_speaker?0xFF:0);
 125.568 +                break;
 125.569 +                case 0xD9: /*Exit 16-bit auto-init mode*/
 125.570 +                if (sbtype<SB16) break;
 125.571 +                sb_16_autoinit=0;
 125.572 +                break;
 125.573 +                case 0xDA: /*Exit 8-bit auto-init mode*/
 125.574 +                sb_8_autoinit=0;
 125.575 +                break;
 125.576 +                case 0xE0: /*DSP identification*/
 125.577 +                sb_add_data(~sb_data[0]);
 125.578 +                break;
 125.579 +                case 0xE1: /*Get DSP version*/
 125.580 +                sb_add_data(sb_dsp_versions[sbtype]>>8);
 125.581 +                sb_add_data(sb_dsp_versions[sbtype]&0xFF);
 125.582 +                break;
 125.583 +                case 0xE2: /*Stupid ID/protection*/
 125.584 +                for (c=0;c<8;c++)
 125.585 +                    if (sb_data[0]&(1<<c)) sbe2+=sbe2dat[sbe2count&3][c];
 125.586 +                sbe2+=sbe2dat[sbe2count&3][8];
 125.587 +                sbe2count++;
 125.588 +                sb_8_write_dma(sbe2);
 125.589 +                break;
 125.590 +                case 0xE3: /*DSP copyright*/
 125.591 +                if (sbtype<SB16) break;
 125.592 +                c=0;
 125.593 +                while (sb16_copyright[c])
 125.594 +                      sb_add_data(sb16_copyright[c++]);
 125.595 +                sb_add_data(0);
 125.596 +                break;
 125.597 +                case 0xE4: /*Write test register*/
 125.598 +                sb_test=sb_data[0];
 125.599 +                break;
 125.600 +                case 0xE8: /*Read test register*/
 125.601 +                sb_add_data(sb_test);
 125.602 +                break;
 125.603 +                case 0xF2: /*Trigger 8-bit IRQ*/
 125.604 +//                pclog("Trigger IRQ\n");
 125.605 +                sb_irq(1);
 125.606 +                break;
 125.607 +                case 0xE7: /*???*/
 125.608 +                case 0xFA: /*???*/
 125.609 +                break;
 125.610 +                case 0x07: /*No, that's not how you program auto-init DMA*/
 125.611 +                case 0xFF:
 125.612 +                break;
 125.613 +                case 0x08: /*ASP get version*/
 125.614 +                if (sbtype<SB16) break;
 125.615 +                sb_add_data(0x18);
 125.616 +                break;
 125.617 +                case 0x0E: /*ASP set register*/
 125.618 +                if (sbtype<SB16) break;
 125.619 +                sb_asp_regs[sb_data[0]] = sb_data[1];
 125.620 +//                pclog("ASP write reg %02X %02X\n", sb_data[0], sb_data[1]);
 125.621 +                break;
 125.622 +                case 0x0F: /*ASP get register*/
 125.623 +                if (sbtype<SB16) break;
 125.624 +//                sb_add_data(0);
 125.625 +                sb_add_data(sb_asp_regs[sb_data[0]]);
 125.626 +//                pclog("ASP read reg %02X %02X\n", sb_data[0], sb_asp_regs[sb_data[0]]);
 125.627 +                break;
 125.628 +                case 0xF9:
 125.629 +                if (sbtype<SB16) break;
 125.630 +                if (sb_data[0] == 0x0e)      sb_add_data(0xff);
 125.631 +                else if (sb_data[0] == 0x0f) sb_add_data(0x07);
 125.632 +                else if (sb_data[0] == 0x37) sb_add_data(0x38);
 125.633 +                else                         sb_add_data(0x00);
 125.634 +                case 0x04:
 125.635 +                case 0x05:
 125.636 +                break;
 125.637 +//                default:
 125.638 +//                fatal("Exec bad SB command %02X\n",sb_command);
 125.639 +        }
 125.640 +}
 125.641 +        
 125.642 +void sb_write(uint16_t a, uint8_t v)
 125.643 +{
 125.644 +        int temp;
 125.645 +        int c;
 125.646 +//        printf("Write soundblaster %04X %02X %04X:%04X %02X\n",a,v,cs>>4,pc,sb_command);
 125.647 +        switch (a&0xF)
 125.648 +        {
 125.649 +                case 0: case 1: case 2: case 3: /*OPL or Gameblaster*/
 125.650 +                if (GAMEBLASTER && sbtype < SBPRO)
 125.651 +                   writecms(a, v);
 125.652 +                else if (sbtype >= SBPRO)
 125.653 +                   adlib_write(a,v); 
 125.654 +                return;
 125.655 +                case 4: mixerindex=v; return;
 125.656 +                case 5:
 125.657 +                sb_mixer[mixerindex]=v;
 125.658 +//                pclog("Write mixer data %02X %02X\n",mixerindex,sb_mixer[mixerindex]);
 125.659 +                if (sbtype==SB16)
 125.660 +                {
 125.661 +                        switch (mixerindex)
 125.662 +                        {
 125.663 +                                case 0x22:
 125.664 +                                sb_mixer[0x30]=((sb_mixer[0x22]>>4)|0x11)<<3;
 125.665 +                                sb_mixer[0x31]=((sb_mixer[0x22]&0xF)|0x11)<<3;
 125.666 +                                break;
 125.667 +                                case 0x04:
 125.668 +                                sb_mixer[0x32]=((sb_mixer[0x04]>>4)|0x11)<<3;
 125.669 +                                sb_mixer[0x33]=((sb_mixer[0x04]&0xF)|0x11)<<3;
 125.670 +                                break;
 125.671 +                                case 0x26:
 125.672 +                                sb_mixer[0x34]=((sb_mixer[0x26]>>4)|0x11)<<3;
 125.673 +                                sb_mixer[0x35]=((sb_mixer[0x26]&0xF)|0x11)<<3;
 125.674 +                                break;
 125.675 +                                case 0x80:
 125.676 +                                if (v & 1) sb_irqnum = 2;
 125.677 +                                if (v & 2) sb_irqnum = 5;
 125.678 +                                if (v & 4) sb_irqnum = 7;
 125.679 +                                if (v & 8) sb_irqnum = 10;
 125.680 +                                break;
 125.681 +                        }
 125.682 +                }
 125.683 +//                if (!mixerindex) sb_mixer_reset();
 125.684 +                sb_mixer_set();
 125.685 +                return;
 125.686 +                case 6: /*Reset*/
 125.687 +                if (!(v&1) && (sbreset&1))
 125.688 +                {
 125.689 +                        sb_dsp_reset();
 125.690 +                        sb_add_data(0xAA);
 125.691 +                }
 125.692 +                sbreset=v;
 125.693 +                return;
 125.694 +                case 8: case 9: adlib_write(a,v); return; /*OPL*/
 125.695 +                case 0xC: /*Command/data write*/
 125.696 +                if (sb_uart) return;
 125.697 +                if (sb_data_stat==-1)
 125.698 +                {
 125.699 +                        sb_command=v;
 125.700 +//                        if (sb_commands[v]==-1)
 125.701 +//                           fatal("Bad SB command %02X\n",v);
 125.702 +                        sb_data_stat++;
 125.703 +                }
 125.704 +                else
 125.705 +                   sb_data[sb_data_stat++]=v;
 125.706 +                if (sb_data_stat==sb_commands[sb_command] || sb_commands[sb_command]==-1)
 125.707 +                {
 125.708 +                        sb_exec_command();
 125.709 +                        sb_data_stat=-1;
 125.710 +                }
 125.711 +                break;
 125.712 +        }
 125.713 +}
 125.714 +
 125.715 +uint8_t sb_read(uint16_t a)
 125.716 +{
 125.717 +        uint8_t temp;
 125.718 +//        if (a==0x224) output=1;
 125.719 +//        printf("Read soundblaster %04X %04X:%04X\n",a,cs,pc);
 125.720 +        switch (a&0xF)
 125.721 +        {
 125.722 +                case 0: case 1: case 2: case 3: /*OPL or GameBlaster*/
 125.723 +                if (GAMEBLASTER && sbtype < SBPRO)
 125.724 +                   return readcms(a);
 125.725 +                return adlib_read(a); 
 125.726 +                break;
 125.727 +                case 5:
 125.728 +                if (sbtype<SBPRO) return 0;
 125.729 +//                pclog("Read mixer data %02X %02X\n",mixerindex,sb_mixer[mixerindex]);
 125.730 +                if (mixerindex==0x80 && sbtype>=SB16)
 125.731 +                {
 125.732 +                        switch (sb_irqnum)
 125.733 +                        {
 125.734 +                                case 2: return 1; /*IRQ 7*/
 125.735 +                                case 5: return 2; /*IRQ 7*/
 125.736 +                                case 7: return 4; /*IRQ 7*/
 125.737 +                                case 10: return 8; /*IRQ 7*/
 125.738 +                        }
 125.739 +                }
 125.740 +                if (mixerindex==0x81 && sbtype>=SB16) return 0x22; /*DMA 1 and 5*/
 125.741 +                if (mixerindex==0x82 && sbtype>=SB16) return ((sb_irq8)?1:0)|((sb_irq16)?2:0);
 125.742 +                return sb_mixer[mixerindex];
 125.743 +                case 8: case 9: return adlib_read(a); /*OPL*/
 125.744 +                case 0xA: /*Read data*/
 125.745 +                if (sb_uart) return;
 125.746 +                sbreaddat=sb_read_data[sb_read_rp];
 125.747 +                if (sb_read_rp!=sb_read_wp)
 125.748 +                {
 125.749 +                        sb_read_rp++;
 125.750 +                        sb_read_rp&=0xFF;
 125.751 +                }
 125.752 +//                pclog("SB read %02X\n",sbreaddat);
 125.753 +                return sbreaddat;
 125.754 +                case 0xC: /*Write data ready*/
 125.755 +                cycles-=100;
 125.756 +                writebusy++;
 125.757 +                if (writebusy&8) return 0xFF;
 125.758 +                return 0x7F;
 125.759 +                case 0xE: /*Read data ready*/
 125.760 +                picintc(1 << sb_irqnum);
 125.761 +                sb_irq8=sb_irq16=0;
 125.762 +                return (sb_read_rp==sb_read_wp)?0x7f:0xff;
 125.763 +                case 0xF: /*16-bit ack*/
 125.764 +                sb_irq16=0;
 125.765 +                if (!sb_irq8) picintc(1 << sb_irqnum);
 125.766 +                return 0xff;
 125.767 +        }
 125.768 +        return 0;
 125.769 +}
 125.770 +
 125.771 +void sb_init()
 125.772 +{
 125.773 +        int c;
 125.774 +        
 125.775 +        sb_reset();
 125.776 +        
 125.777 +        io_sethandler(0x0220, 0x0010, sb_read, NULL, NULL, sb_write, NULL, NULL);
 125.778 +}
 125.779 +
 125.780 +
 125.781 +int sbshift4[8]={-2,-1,0,0,1,1,1,1};
 125.782 +void pollsb()
 125.783 +{
 125.784 +        int tempi,ref;
 125.785 +//        pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output);
 125.786 +        if (sb_8_enable && !sb_8_pause && sb_pausetime<0 && sb_8_output)
 125.787 +        {
 125.788 +//                pclog("Dopoll %i %02X %i\n", sb_8_length, sb_8_format, sblatcho);
 125.789 +                switch (sb_8_format)
 125.790 +                {
 125.791 +                        case 0x00: /*Mono unsigned*/
 125.792 +                        sbdat=(sb_8_read_dma()^0x80)<<8;
 125.793 +                        if (sbtype>=SBPRO && sbtype<SB16 && sb_mixer[0xE]&2)
 125.794 +                        {
 125.795 +                                if (sbleftright) sbdatl=sbdat;
 125.796 +                                else             sbdatr=sbdat;
 125.797 +                                sbleftright=!sbleftright;
 125.798 +                        }
 125.799 +                        else
 125.800 +                           sbdatl=sbdatr=sbdat;
 125.801 +                        sb_8_length--;
 125.802 +                        break;
 125.803 +                        case 0x10: /*Mono signed*/
 125.804 +                        sbdat=sb_8_read_dma()<<8;
 125.805 +                        if (sbtype>=SBPRO && sbtype<SB16 && sb_mixer[0xE]&2)
 125.806 +                        {
 125.807 +                                if (sbleftright) sbdatl=sbdat;
 125.808 +                                else             sbdatr=sbdat;
 125.809 +                                sbleftright=!sbleftright;
 125.810 +                        }
 125.811 +                        else
 125.812 +                           sbdatl=sbdatr=sbdat;
 125.813 +                        sb_8_length--;
 125.814 +                        break;
 125.815 +                        case 0x20: /*Stereo unsigned*/
 125.816 +                        sbdatl=(sb_8_read_dma()^0x80)<<8;
 125.817 +                        sbdatr=(sb_8_read_dma()^0x80)<<8;
 125.818 +                        sb_8_length-=2;
 125.819 +                        break;
 125.820 +                        case 0x30: /*Stereo signed*/
 125.821 +                        sbdatl=sb_8_read_dma()<<8;
 125.822 +                        sbdatr=sb_8_read_dma()<<8;
 125.823 +                        sb_8_length-=2;
 125.824 +                        break;
 125.825 +
 125.826 +                        case ADPCM_4:
 125.827 +                        if (sbdacpos) tempi=(sbdat2&0xF)+sbstep;
 125.828 +                        else          tempi=(sbdat2>>4)+sbstep;
 125.829 +                        if (tempi<0) tempi=0;
 125.830 +                        if (tempi>63) tempi=63;
 125.831 +
 125.832 +                        ref = sbref + scaleMap4[tempi];
 125.833 +                        if (ref > 0xff) sbref = 0xff;
 125.834 +                        else if (ref < 0x00) sbref = 0x00;
 125.835 +                        else sbref = ref;
 125.836 +
 125.837 +                        sbstep = (sbstep + adjustMap4[tempi]) & 0xff;
 125.838 +
 125.839 +                        sbdat=(sbref^0x80)<<8;
 125.840 +
 125.841 +                        sbdacpos++;
 125.842 +                        if (sbdacpos>=2)
 125.843 +                        {
 125.844 +                                sbdacpos=0;
 125.845 +                                sbdat2=sb_8_read_dma();
 125.846 +                                sb_8_length--;
 125.847 +                        }
 125.848 +
 125.849 +                        if (sbtype>=SBPRO && sbtype<SB16 && sb_mixer[0xE]&2)
 125.850 +                        {
 125.851 +                                if (sbleftright) sbdatl=sbdat;
 125.852 +                                else             sbdatr=sbdat;
 125.853 +                                sbleftright=!sbleftright;
 125.854 +                        }
 125.855 +                        else
 125.856 +                           sbdatl=sbdatr=sbdat;
 125.857 +                        break;
 125.858 +                        
 125.859 +                        case ADPCM_26:
 125.860 +                        if (!sbdacpos)        tempi=(sbdat2>>5)+sbstep;
 125.861 +                        else if (sbdacpos==1) tempi=((sbdat2>>2)&7)+sbstep;
 125.862 +                        else                  tempi=((sbdat2<<1)&7)+sbstep;
 125.863 +
 125.864 +                        if (tempi<0) tempi=0;
 125.865 +                        if (tempi>39) tempi=39;
 125.866 +
 125.867 +                        ref = sbref + scaleMap26[tempi];
 125.868 +                        if (ref > 0xff) sbref = 0xff;
 125.869 +                        else if (ref < 0x00) sbref = 0x00;
 125.870 +                        else sbref = ref;
 125.871 +                        sbstep = (sbstep + adjustMap26[tempi]) & 0xff;
 125.872 +
 125.873 +                        sbdat=(sbref^0x80)<<8;
 125.874 +
 125.875 +                        sbdacpos++;
 125.876 +                        if (sbdacpos>=3)
 125.877 +                        {
 125.878 +                                sbdacpos=0;
 125.879 +                                sbdat2=readdma1();
 125.880 +                                sb_8_length--;
 125.881 +                        }
 125.882 +
 125.883 +                        if (sbtype>=SBPRO && sbtype<SB16 && sb_mixer[0xE]&2)
 125.884 +                        {
 125.885 +                                if (sbleftright) sbdatl=sbdat;
 125.886 +                                else             sbdatr=sbdat;
 125.887 +                                sbleftright=!sbleftright;
 125.888 +                        }
 125.889 +                        else
 125.890 +                           sbdatl=sbdatr=sbdat;
 125.891 +                        break;
 125.892 +
 125.893 +                        case ADPCM_2:
 125.894 +                        tempi=((sbdat2>>((3-sbdacpos)*2))&3)+sbstep;
 125.895 +                        if (tempi<0) tempi=0;
 125.896 +                        if (tempi>23) tempi=23;
 125.897 +
 125.898 +                        ref = sbref + scaleMap2[tempi];
 125.899 +                        if (ref > 0xff) sbref = 0xff;
 125.900 +                        else if (ref < 0x00) sbref = 0x00;
 125.901 +                        else sbref = ref;
 125.902 +                        sbstep = (sbstep + adjustMap2[tempi]) & 0xff;
 125.903 +                        
 125.904 +                        sbdat=(sbref^0x80)<<8;
 125.905 +
 125.906 +                        sbdacpos++;
 125.907 +                        if (sbdacpos>=4)
 125.908 +                        {
 125.909 +                                sbdacpos=0;
 125.910 +                                sbdat2=readdma1();
 125.911 +                        }
 125.912 +
 125.913 +                        if (sbtype>=SBPRO && sbtype<SB16 && sb_mixer[0xE]&2)
 125.914 +                        {
 125.915 +                                if (sbleftright) sbdatl=sbdat;
 125.916 +                                else             sbdatr=sbdat;
 125.917 +                                sbleftright=!sbleftright;
 125.918 +                        }
 125.919 +                        else
 125.920 +                           sbdatl=sbdatr=sbdat;
 125.921 +                        break;
 125.922 +
 125.923 +//                        default:
 125.924 +                                //fatal("Unrecognised SB 8-bit format %02X\n",sb_8_format);
 125.925 +                }
 125.926 +                
 125.927 +                if (sb_8_length<0)
 125.928 +                {
 125.929 +//                        pclog("DMA over %i %i\n", sb_8_autoinit, sb_irqnum);
 125.930 +                        if (sb_8_autoinit) sb_8_length=sb_8_autolen;
 125.931 +                        else               sb_8_enable=sbenable=0;
 125.932 +                        sb_irq(1);
 125.933 +                }
 125.934 +        }
 125.935 +        if (sb_16_enable && !sb_16_pause && sb_pausetime<0 && sb_16_output)
 125.936 +        {
 125.937 +                switch (sb_16_format)
 125.938 +                {
 125.939 +                        case 0x00: /*Mono unsigned*/
 125.940 +                        sbdatl=sbdatr=sb_16_read_dma()^0x8000;
 125.941 +                        sb_16_length--;
 125.942 +                        break;
 125.943 +                        case 0x10: /*Mono signed*/
 125.944 +                        sbdatl=sbdatr=sb_16_read_dma();
 125.945 +                        sb_16_length--;
 125.946 +                        break;
 125.947 +                        case 0x20: /*Stereo unsigned*/
 125.948 +                        sbdatl=sb_16_read_dma()^0x8000;
 125.949 +                        sbdatr=sb_16_read_dma()^0x8000;
 125.950 +                        sb_16_length-=2;
 125.951 +                        break;
 125.952 +                        case 0x30: /*Stereo signed*/
 125.953 +                        sbdatl=sb_16_read_dma();
 125.954 +                        sbdatr=sb_16_read_dma();
 125.955 +                        sb_16_length-=2;
 125.956 +                        break;
 125.957 +
 125.958 +//                        default:
 125.959 +//                                fatal("Unrecognised SB 16-bit format %02X\n",sb_16_format);
 125.960 +                }
 125.961 +
 125.962 +                if (sb_16_length<0)
 125.963 +                {
 125.964 +//                        pclog("16DMA over %i\n",sb_16_autoinit);
 125.965 +                        if (sb_16_autoinit) sb_16_length=sb_16_autolen;
 125.966 +                        else                sb_16_enable=sbenable=0;
 125.967 +                        sb_irq(0);
 125.968 +                }
 125.969 +        }
 125.970 +        if (sb_pausetime>-1)
 125.971 +        {
 125.972 +                sb_pausetime--;
 125.973 +                if (sb_pausetime<0)
 125.974 +                {
 125.975 +                        sb_irq(1);
 125.976 +                        sbenable=sb_8_enable;
 125.977 +                        pclog("SB pause over\n");
 125.978 +                }
 125.979 +        }
 125.980 +}
 125.981 +
 125.982 +void sb_poll_i()
 125.983 +{
 125.984 +//        pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output);        
 125.985 +        if (sb_8_enable && !sb_8_pause && sb_pausetime<0 && !sb_8_output)
 125.986 +        {
 125.987 +                switch (sb_8_format)
 125.988 +                {
 125.989 +                        case 0x00: /*Mono unsigned*/
 125.990 +                        sb_8_write_dma(0x80);
 125.991 +                        sb_8_length--;
 125.992 +                        break;
 125.993 +                        case 0x10: /*Mono signed*/
 125.994 +                        sb_8_write_dma(0x00);
 125.995 +                        sb_8_length--;
 125.996 +                        break;
 125.997 +                        case 0x20: /*Stereo unsigned*/
 125.998 +                        sb_8_write_dma(0x80);
 125.999 +                        sb_8_write_dma(0x80);
125.1000 +                        sb_8_length-=2;
125.1001 +                        break;
125.1002 +                        case 0x30: /*Stereo signed*/
125.1003 +                        sb_8_write_dma(0x00);
125.1004 +                        sb_8_write_dma(0x00);
125.1005 +                        sb_8_length-=2;
125.1006 +                        break;
125.1007 +
125.1008 +//                        default:
125.1009 +//                                fatal("Unrecognised SB 8-bit input format %02X\n",sb_8_format);
125.1010 +                }
125.1011 +                
125.1012 +                if (sb_8_length<0)
125.1013 +                {
125.1014 +//                        pclog("Input DMA over %i\n",sb_8_autoinit);
125.1015 +                        if (sb_8_autoinit) sb_8_length=sb_8_autolen;
125.1016 +                        else               sb_8_enable=sbenable=0;
125.1017 +                        sb_irq(1);
125.1018 +                }
125.1019 +        }
125.1020 +        if (sb_16_enable && !sb_16_pause && sb_pausetime<0 && !sb_16_output)
125.1021 +        {
125.1022 +                switch (sb_16_format)
125.1023 +                {
125.1024 +                        case 0x00: /*Unsigned mono*/
125.1025 +                        sb_16_write_dma(0x8000);
125.1026 +                        sb_16_length--;
125.1027 +                        break;
125.1028 +                        case 0x10: /*Signed mono*/
125.1029 +                        sb_16_write_dma(0);
125.1030 +                        sb_16_length--;
125.1031 +                        break;
125.1032 +                        case 0x20: /*Unsigned stereo*/
125.1033 +                        sb_16_write_dma(0x8000);
125.1034 +                        sb_16_write_dma(0x8000);
125.1035 +                        sb_16_length-=2;
125.1036 +                        break;
125.1037 +                        case 0x30: /*Signed stereo*/
125.1038 +                        sb_16_write_dma(0);
125.1039 +                        sb_16_write_dma(0);
125.1040 +                        sb_16_length-=2;
125.1041 +                        break;
125.1042 +                        
125.1043 +//                        default:
125.1044 +//                                fatal("Unrecognised SB 16-bit input format %02X\n",sb_16_format);
125.1045 +                }
125.1046 +                
125.1047 +                if (sb_16_length<0)
125.1048 +                {
125.1049 +//                        pclog("16iDMA over %i\n",sb_16_autoinit);
125.1050 +                        if (sb_16_autoinit) sb_16_length=sb_16_autolen;
125.1051 +                        else                sb_16_enable=sbenable=0;
125.1052 +                        sb_irq(0);
125.1053 +                }
125.1054 +        }
125.1055 +}
125.1056 +
125.1057 +int16_t sbbuffer[2][SOUNDBUFLEN+20];
125.1058 +int sbbufferpos=0;
125.1059 +int _sampcnt=0;
125.1060 +int16_t sb_filtbuf[4]={0,0,0,0};
125.1061 +void getsbsamp()
125.1062 +{
125.1063 +        int vocl=sbpmixer.vocl*sbpmixer.masl;
125.1064 +        int vocr=sbpmixer.vocr*sbpmixer.masr;
125.1065 +        int16_t sbdat[2];
125.1066 +        double t;
125.1067 +        
125.1068 +        vocl=256-vocl;
125.1069 +        vocr=256-vocr;
125.1070 +        if (!vocl) vocl=1;
125.1071 +        if (!vocr) vocr=1;
125.1072 +        if (sbbufferpos>=(SOUNDBUFLEN+20)) return;
125.1073 +        
125.1074 +        sbdat[0]=sbdatl;
125.1075 +        sbdat[1]=sbdatr;
125.1076 +
125.1077 +        if (mixer.filter)
125.1078 +        {
125.1079 +                /*3.2kHz output filter*/
125.1080 +                sbdat[0]=(int16_t)(sb_iir(0,(float)sbdat[0])/1.3);
125.1081 +                sbdat[1]=(int16_t)(sb_iir(1,(float)sbdat[1])/1.3);
125.1082 +        }
125.1083 +
125.1084 +        sbbuffer[0][sbbufferpos]=sbdat[0];
125.1085 +        sbbuffer[1][sbbufferpos]=sbdat[1];
125.1086 +        sbbufferpos++;
125.1087 +}
125.1088 +
125.1089 +void addsb(int16_t *p)
125.1090 +{
125.1091 +        int c;
125.1092 +        if (sbbufferpos>SOUNDBUFLEN) sbbufferpos=SOUNDBUFLEN;
125.1093 +//        printf("Addsb - %i %04X\n",sbbufferpos,p[0]);
125.1094 +        for (c=0;c<sbbufferpos;c++)
125.1095 +        {
125.1096 +                p[c<<1]+=(((sbbuffer[0][c]/3)*mixer.voice_l)>>16);
125.1097 +                p[(c<<1)+1]+=(((sbbuffer[1][c]/3)*mixer.voice_r)>>16);
125.1098 +//                if (!c) pclog("V %04X %04X %04X\n",sbbuffer[0][c],p[c<<1],mixer.voice_l);
125.1099 +        }
125.1100 +        for (;c<SOUNDBUFLEN;c++)
125.1101 +        {
125.1102 +                p[c<<1]+=(((sbbuffer[0][sbbufferpos-1]/3)*mixer.voice_l)>>16);
125.1103 +                p[(c<<1)+1]+=(((sbbuffer[0][sbbufferpos-1]/3)*mixer.voice_l)>>16);
125.1104 +        }
125.1105 +        sbbufferpos=0;
125.1106 +}
125.1107 +
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/src/serial.c	Sun Apr 21 14:54:35 2013 +0100
   126.3 @@ -0,0 +1,210 @@
   126.4 +#include "ibm.h"
   126.5 +#include "io.h"
   126.6 +#include "mouse.h"
   126.7 +#include "serial.h"
   126.8 +
   126.9 +SERIAL serial,serial2;
  126.10 +
  126.11 +int mousepos=-1;
  126.12 +int mousedelay;
  126.13 +uint8_t serial_fifo[256];
  126.14 +int serial_fifo_read, serial_fifo_write;
  126.15 +
  126.16 +void (*serial_rcr)();
  126.17 +
  126.18 +void serial_reset()
  126.19 +{
  126.20 +        serial.iir=serial.ier=serial.lcr=0;
  126.21 +        serial2.iir=serial2.ier=serial2.lcr=0;
  126.22 +        mousedelay=0;
  126.23 +        serial_fifo_read = serial_fifo_write = 0;
  126.24 +}
  126.25 +
  126.26 +void serial_write_fifo(uint8_t dat)
  126.27 +{
  126.28 +        serial_fifo[serial_fifo_write] = dat;
  126.29 +        serial_fifo_write = (serial_fifo_write + 1) & 0xFF;
  126.30 +        if (!(serial.linestat & 1))
  126.31 +        {
  126.32 +                serial.linestat|=1;
  126.33 +                if (serial.mctrl&8) picint(0x10);
  126.34 +                serial.iir=4;
  126.35 +        }
  126.36 +}
  126.37 +
  126.38 +uint8_t serial_read_fifo()
  126.39 +{
  126.40 +        uint8_t temp = serial_fifo[serial_fifo_read];
  126.41 +        if (serial_fifo_read != serial_fifo_write)
  126.42 +           serial_fifo_read = (serial_fifo_read + 1) & 0xFF;
  126.43 +        return temp;
  126.44 +}
  126.45 +
  126.46 +void sendserial(uint8_t dat)
  126.47 +{
  126.48 +        serial.rcr=dat;
  126.49 +        serial.linestat|=1;
  126.50 +        if (serial.mctrl&8) picint(0x10);
  126.51 +        serial.iir=4;
  126.52 +}
  126.53 +
  126.54 +void serial_write(uint16_t addr, uint8_t val)
  126.55 +{
  126.56 +//        printf("Write serial %03X %02X %04X:%04X\n",addr,val,CS,pc);
  126.57 +        switch (addr&7)
  126.58 +        {
  126.59 +                case 0:
  126.60 +                if (serial.lcr&0x80 && !AMSTRADIO)
  126.61 +                {
  126.62 +                        serial.dlab1=val;
  126.63 +                        return;
  126.64 +                }
  126.65 +                serial.thr=val;
  126.66 +                serial.linestat|=0x20;
  126.67 +                if (serial.mctrl&0x10)
  126.68 +                {
  126.69 +                        serial_write_fifo(val);
  126.70 +//                        serial.rcr=val;
  126.71 +//                        serial.linestat|=1;
  126.72 +                }
  126.73 +                break;
  126.74 +                case 1:
  126.75 +                if (serial.lcr&0x80 && !AMSTRADIO)
  126.76 +                {
  126.77 +                        serial.dlab2=val;
  126.78 +                        return;
  126.79 +                }
  126.80 +                serial.ier=val;
  126.81 +                break;
  126.82 +                case 3: serial.lcr=val; break;
  126.83 +                case 4:
  126.84 +                if ((val&2) && !(serial.mctrl&2))
  126.85 +                {
  126.86 +                        if (serial_rcr)
  126.87 +                           serial_rcr();
  126.88 +//                        printf("RCR raised! sending M\n");
  126.89 +                }
  126.90 +                serial.mctrl=val;
  126.91 +                break;
  126.92 +        }
  126.93 +}
  126.94 +
  126.95 +uint8_t serial_read(uint16_t addr)
  126.96 +{
  126.97 +        uint8_t temp;
  126.98 +//        printf("Read serial %03X %04X(%08X):%04X %i %i  ", addr, CS, cs, pc, mousedelay, ins);
  126.99 +        switch (addr&7)
 126.100 +        {
 126.101 +                case 0:
 126.102 +                if (serial.lcr&0x80 && !AMSTRADIO) return serial.dlab1;
 126.103 +//                picintc(0x10);
 126.104 +                serial.iir=1;
 126.105 +                serial.linestat&=~1;
 126.106 +                temp=serial_read_fifo();
 126.107 +                if (serial_fifo_read != serial_fifo_write)
 126.108 +                {
 126.109 +                        mousepos = 0;
 126.110 +                        mousedelay = 1000;
 126.111 +//                        pclog("Next FIFO\n");
 126.112 +                }
 126.113 +                break;
 126.114 +                case 1:
 126.115 +                if (serial.lcr&0x80 && !AMSTRADIO) temp = serial.dlab2;
 126.116 +                else                               temp = 0;
 126.117 +                break;
 126.118 +                case 2: temp=serial.iir; break;
 126.119 +                case 3: temp=serial.lcr; break;
 126.120 +                case 4: temp=serial.mctrl; break;
 126.121 +                case 5: temp=serial.linestat; serial.linestat|=0x60; break;
 126.122 +                default: temp=0;
 126.123 +        }
 126.124 +//        printf("%02X\n",temp);
 126.125 +        return temp;
 126.126 +}
 126.127 +
 126.128 +void serial2_write(uint16_t addr, uint8_t val)
 126.129 +{
 126.130 +//        printf("Write serial2 %03X %02X %04X:%04X\n",addr,val,cs>>4,pc);
 126.131 +        switch (addr&7)
 126.132 +        {
 126.133 +                case 0:
 126.134 +                if (serial2.lcr&0x80 && !AMSTRADIO)
 126.135 +                {
 126.136 +                        serial2.dlab1=val;
 126.137 +                        return;
 126.138 +                }
 126.139 +                serial2.thr=val;
 126.140 +                serial2.linestat|=0x20;
 126.141 +                if (serial2.mctrl&0x10)
 126.142 +                {
 126.143 +                        serial2.rcr=val;
 126.144 +                        serial2.linestat|=1;
 126.145 +                }
 126.146 +                break;
 126.147 +                case 1:
 126.148 +                if (serial2.lcr&0x80 && !AMSTRADIO)
 126.149 +                {
 126.150 +                        serial2.dlab2=val;
 126.151 +                        return;
 126.152 +                }
 126.153 +                serial2.ier=val;
 126.154 +                break;
 126.155 +                case 3: serial2.lcr=val; break;
 126.156 +                case 4:
 126.157 +                serial2.mctrl=val;
 126.158 +                break;
 126.159 +        }
 126.160 +}
 126.161 +
 126.162 +uint8_t serial2_read(uint16_t addr)
 126.163 +{
 126.164 +        uint8_t temp;
 126.165 +//        printf("Read serial2 %03X %04X:%04X\n",addr,cs>>4,pc);
 126.166 +        switch (addr&7)
 126.167 +        {
 126.168 +                case 0:
 126.169 +                if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab1;
 126.170 +                serial2.iir=1;
 126.171 +                serial2.linestat&=~1;
 126.172 +                temp=serial2.rcr;
 126.173 +                break;
 126.174 +                case 1:
 126.175 +                if (serial2.lcr&0x80 && !AMSTRADIO) return serial2.dlab2;
 126.176 +                temp=0;
 126.177 +                break;
 126.178 +                case 2: temp=serial2.iir; break;
 126.179 +                case 3: temp=serial2.lcr; break;
 126.180 +                case 4: temp=serial2.mctrl; break;
 126.181 +                case 5: temp=serial2.linestat; break;
 126.182 +                default: temp=0;
 126.183 +        }
 126.184 +//        printf("%02X\n",temp);
 126.185 +        return temp;
 126.186 +}
 126.187 +
 126.188 +
 126.189 +/*Tandy might need COM1 at 2f8*/
 126.190 +void serial1_init(uint16_t addr)
 126.191 +{
 126.192 +        io_sethandler(addr, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL);
 126.193 +        serial_rcr = NULL;
 126.194 +}
 126.195 +void serial1_remove()
 126.196 +{
 126.197 +        io_removehandler(0x2e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL);
 126.198 +        io_removehandler(0x2f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL);
 126.199 +        io_removehandler(0x3e8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL);
 126.200 +        io_removehandler(0x3f8, 0x0008, serial_read,  NULL, NULL, serial_write,  NULL, NULL);
 126.201 +}
 126.202 +
 126.203 +void serial2_init(uint16_t addr)
 126.204 +{
 126.205 +        io_sethandler(addr, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL);
 126.206 +}
 126.207 +void serial2_remove()
 126.208 +{
 126.209 +        io_removehandler(0x2e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL);
 126.210 +        io_removehandler(0x2f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL);
 126.211 +        io_removehandler(0x3e8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL);
 126.212 +        io_removehandler(0x3f8, 0x0008, serial2_read, NULL, NULL, serial2_write, NULL, NULL);
 126.213 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/src/serial.h	Sun Apr 21 14:54:35 2013 +0100
   127.3 @@ -0,0 +1,17 @@
   127.4 +void serial1_init(uint16_t addr);
   127.5 +void serial2_init(uint16_t addr);
   127.6 +void serial1_remove();
   127.7 +void serial2_remove();
   127.8 +void serial_reset();
   127.9 +
  127.10 +typedef struct
  127.11 +{
  127.12 +        uint8_t linestat,thr,mctrl,rcr,iir,ier,lcr;
  127.13 +        uint8_t dlab1,dlab2;
  127.14 +} SERIAL;
  127.15 +
  127.16 +extern SERIAL serial,serial2;
  127.17 +
  127.18 +extern int serial_fifo_read, serial_fifo_write;
  127.19 +
  127.20 +extern void (*serial_rcr)();
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/src/sound.c	Sun Apr 21 14:54:35 2013 +0100
   128.3 @@ -0,0 +1,180 @@
   128.4 +#include <stdio.h>
   128.5 +#include "ibm.h"
   128.6 +#include "filters.h"
   128.7 +
   128.8 +int soundon = 1;
   128.9 +int16_t *adbuffer,*adbuffer2;
  128.10 +int16_t *psgbuffer;
  128.11 +uint16_t *cmsbuffer;
  128.12 +int16_t *spkbuffer;
  128.13 +int16_t *outbuffer;
  128.14 +uint16_t *gusbuffer;
  128.15 +
  128.16 +void initsound()
  128.17 +{
  128.18 +        initalmain(0,NULL);
  128.19 +        inital();
  128.20 +//        install_sound(DIGI_AUTODETECT,MIDI_NONE,0);
  128.21 +//        as=play_audio_stream(SOUNDBUFLEN,16,1,48000,255,128);
  128.22 +        adbuffer=malloc((SOUNDBUFLEN)*2);
  128.23 +        adbuffer2=malloc((SOUNDBUFLEN)*2);
  128.24 +        psgbuffer=malloc((SOUNDBUFLEN)*2);
  128.25 +        cmsbuffer=malloc((SOUNDBUFLEN)*2*2);
  128.26 +        gusbuffer=malloc((SOUNDBUFLEN)*2*2);
  128.27 +        spkbuffer=malloc(((SOUNDBUFLEN)*2)+32);
  128.28 +        outbuffer=malloc((SOUNDBUFLEN)*2*2);
  128.29 +}
  128.30 +
  128.31 +int adpoll=0;
  128.32 +void pollad()
  128.33 +{
  128.34 +/*        if (adpoll>=20) return;
  128.35 +        getadlibl(adbuffer+(adpoll*(48000/200)),48000/200);
  128.36 +        getadlibr(adbuffer2+(adpoll*(48000/200)),48000/200);
  128.37 +        adpoll++;*/
  128.38 +//        printf("ADPOLL %i\n",adpoll);
  128.39 +}
  128.40 +
  128.41 +void polladlib()
  128.42 +{
  128.43 +        getadlib(adbuffer+(adpoll),adbuffer2+(adpoll),1);
  128.44 +        adpoll++;
  128.45 +}
  128.46 +
  128.47 +int psgpoll=0;
  128.48 +void pollpsg()
  128.49 +{
  128.50 +        if (psgpoll>=20) return;
  128.51 +        getpsg(psgbuffer+(psgpoll*(48000/200)),48000/200);
  128.52 +        psgpoll++;
  128.53 +}
  128.54 +
  128.55 +int cmspoll=0;
  128.56 +void pollcms()
  128.57 +{
  128.58 +        if (cmspoll>=20) return;
  128.59 +        getcms(cmsbuffer+(cmspoll*(48000/200)*2),48000/200);
  128.60 +        cmspoll++;
  128.61 +}
  128.62 +
  128.63 +int guspoll=0;
  128.64 +void pollgussnd()
  128.65 +{
  128.66 +        if (guspoll>=20) return;
  128.67 +        getgus(gusbuffer+(guspoll*(48000/200)*2),48000/200);
  128.68 +        guspoll++;
  128.69 +}
  128.70 +
  128.71 +int spkpos=0;
  128.72 +int wasgated = 0;
  128.73 +void pollspk()
  128.74 +{
  128.75 +        if (spkpos>=SOUNDBUFLEN) return;
  128.76 +//        printf("SPeaker - %i %i %i %02X\n",speakval,gated,speakon,pit.m[2]);
  128.77 +        if (gated)
  128.78 +        {
  128.79 +                if (!pit.m[2] || pit.m[2]==4)
  128.80 +                   spkbuffer[spkpos]=speakval;
  128.81 +                else 
  128.82 +                   spkbuffer[spkpos]=(speakon)?0x1400:0;
  128.83 +        }
  128.84 +        else
  128.85 +           spkbuffer[spkpos]=(wasgated)?0x1400:0;
  128.86 +        spkpos++;
  128.87 +        wasgated=0;
  128.88 +}
  128.89 +
  128.90 +FILE *soundf;
  128.91 +
  128.92 +static int16_t cd_buffer[(SOUNDBUFLEN) * 2];
  128.93 +void pollsound()
  128.94 +{
  128.95 +        int c;
  128.96 +        int16_t t[4];
  128.97 +        uint32_t pos;
  128.98 +//        printf("Pollsound! %i\n",soundon);
  128.99 +//        if (soundon)
 128.100 +//        {
 128.101 +                for (c=0;c<(SOUNDBUFLEN);c++) outbuffer[c<<1]=outbuffer[(c<<1)+1]=0;
 128.102 +                for (c=0;c<(SOUNDBUFLEN);c++)
 128.103 +                {
 128.104 +                        outbuffer[c<<1]+=((adbuffer[c]*mixer.fm_l)>>16);
 128.105 +                        outbuffer[(c<<1)+1]+=((adbuffer[c]*mixer.fm_r)>>16);
 128.106 +//                        if (!c) pclog("F %04X %04X %04X\n",adbuffer[c],outbuffer[c<<1],mixer.fm_l);
 128.107 +                }
 128.108 +                addsb(outbuffer);
 128.109 +                for (c=0;c<(SOUNDBUFLEN);c++)
 128.110 +                {
 128.111 +//                        if (!c) pclog("M %04X ",outbuffer[c<<1]);
 128.112 +                        outbuffer[c<<1]=(outbuffer[c<<1]*mixer.master_l)>>16;
 128.113 +                        outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]*mixer.master_r)>>16;
 128.114 +//                        if (!c) pclog("%04X %04X\n",outbuffer[c<<1],mixer.master_l);
 128.115 +                }
 128.116 +                if (mixer.bass_l!=8 || mixer.bass_r!=8 || mixer.treble_l!=8 || mixer.treble_r!=8)
 128.117 +                {
 128.118 +                        for (c=0;c<(SOUNDBUFLEN);c++)
 128.119 +                        {
 128.120 +                                if (mixer.bass_l>8)   outbuffer[c<<1]    =(outbuffer[c<<1]    +(((int16_t)low_iir(0,(float)outbuffer[c<<1])         *(mixer.bass_l-8))>>1))*((15-mixer.bass_l)+16)>>5;
 128.121 +                                if (mixer.bass_r>8)   outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_iir(1,(float)outbuffer[(c<<1)+1])     *(mixer.bass_r-8))>>1))*((15-mixer.bass_r)+16)>>5;
 128.122 +                                if (mixer.treble_l>8) outbuffer[c<<1]    =(outbuffer[c<<1]    +(((int16_t)high_iir(0,(float)outbuffer[c<<1])        *(mixer.treble_l-8))>>1))*((15-mixer.treble_l)+16)>>5;
 128.123 +                                if (mixer.treble_r>8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_iir(1,(float)outbuffer[(c<<1)+1])    *(mixer.treble_r-8))>>1))*((15-mixer.treble_r)+16)>>5;
 128.124 +                                if (mixer.bass_l<8)   outbuffer[c<<1]    =(outbuffer[c<<1]    +(((int16_t)low_cut_iir(0,(float)outbuffer[c<<1])     *(8-mixer.bass_l))>>1))*(mixer.bass_l+16)>>5;
 128.125 +                                if (mixer.bass_r<8)   outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)low_cut_iir(1,(float)outbuffer[(c<<1)+1]) *(8-mixer.bass_r))>>1))*(mixer.bass_r+16)>>5;
 128.126 +                                if (mixer.treble_l<8) outbuffer[c<<1]    =(outbuffer[c<<1]    +(((int16_t)high_cut_iir(0,(float)outbuffer[c<<1])    *(8-mixer.treble_l))>>1))*(mixer.treble_l+16)>>5;
 128.127 +                                if (mixer.treble_r<8) outbuffer[(c<<1)+1]=(outbuffer[(c<<1)+1]+(((int16_t)high_cut_iir(1,(float)outbuffer[(c<<1)+1])*(8-mixer.treble_r))>>1))*(mixer.treble_r+16)>>5;
 128.128 +                        }
 128.129 +                }
 128.130 +                for (c=0;c<(SOUNDBUFLEN);c++)
 128.131 +                {
 128.132 +                        outbuffer[c<<1]+=(spkbuffer[c]/2);
 128.133 +                        outbuffer[(c<<1)+1]+=(spkbuffer[c]/2);
 128.134 +                }
 128.135 +                for (c=0;c<(SOUNDBUFLEN);c++)
 128.136 +                {
 128.137 +                        outbuffer[c<<1]+=(psgbuffer[c]/2);
 128.138 +                        outbuffer[(c<<1)+1]+=(psgbuffer[c]/2);
 128.139 +                }
 128.140 +                for (c=0;c<((SOUNDBUFLEN)*2);c++)
 128.141 +                    outbuffer[c]+=(cmsbuffer[c]/2);
 128.142 +                for (c=0;c<((SOUNDBUFLEN)*2);c++)
 128.143 +                    outbuffer[c]+=(gusbuffer[c]);
 128.144 +                adddac(outbuffer);
 128.145 +                ioctl_audio_callback(cd_buffer, ((SOUNDBUFLEN) * 2  * 441) / 480);
 128.146 +                pos = 0;
 128.147 +                for (c = 0; c < (SOUNDBUFLEN) * 2; c+=2)
 128.148 +                {
 128.149 +                        outbuffer[c]     += cd_buffer[((pos >> 16) << 1)]     / 2;
 128.150 +                        outbuffer[c + 1] += cd_buffer[((pos >> 16) << 1) + 1] / 2;                        
 128.151 +//                        outbuffer[c] += (int16_t)((int32_t)cd_buffer[pos >> 16] * (65536 - (pos & 0xffff))) / 65536;
 128.152 +//                        outbuffer[c] += (int16_t)((int32_t)cd_buffer[(pos >> 16) + 1] * (pos & 0xffff)) / 65536;                        
 128.153 +                        pos += 60211; //(44100 * 65536) / 48000;
 128.154 +                }
 128.155 +                
 128.156 +//                if (!soundf) soundf=fopen("sound.pcm","wb");
 128.157 +//                fwrite(outbuffer,(SOUNDBUFLEN)*2*2,1,soundf);
 128.158 +                if (soundon) givealbuffer(outbuffer);
 128.159 +//        }
 128.160 +//        addsb(outbuffer);
 128.161 +//        adddac(outbuffer);
 128.162 +        adpoll=0;
 128.163 +        psgpoll=0;
 128.164 +        cmspoll=0;
 128.165 +        spkpos=0;
 128.166 +        guspoll=0;
 128.167 +}
 128.168 +
 128.169 +int sndcount;
 128.170 +void pollsound60hz()
 128.171 +{
 128.172 +//        printf("Poll sound %i\n",sndcount);
 128.173 +//                pollad();
 128.174 +                pollpsg();
 128.175 +                pollcms();
 128.176 +                pollgussnd();
 128.177 +                sndcount++;
 128.178 +                if (sndcount==20)
 128.179 +                {
 128.180 +                        sndcount=0;
 128.181 +                        pollsound();
 128.182 +                }
 128.183 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/src/sound.h	Sun Apr 21 14:54:35 2013 +0100
   129.3 @@ -0,0 +1,1 @@
   129.4 +extern int wasgated;
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/src/soundopenal.c	Sun Apr 21 14:54:35 2013 +0100
   130.3 @@ -0,0 +1,143 @@
   130.4 +#define USE_OPENAL
   130.5 +#include <stdio.h>
   130.6 +#include <string.h>
   130.7 +#ifdef USE_OPENAL
   130.8 +#include <AL/al.h>
   130.9 +#include <AL/alut.h>
  130.10 +#endif
  130.11 +#include "ibm.h"
  130.12 +
  130.13 +FILE *allog;
  130.14 +#ifdef USE_OPENAL
  130.15 +ALuint buffers[4]; // front and back buffers
  130.16 +ALuint source;     // audio source
  130.17 +ALenum format;     // internal format
  130.18 +#endif
  130.19 +#define FREQ 48000
  130.20 +#define BUFLEN SOUNDBUFLEN
  130.21 +
  130.22 +void closeal();
  130.23 +
  130.24 +void initalmain(int argc, char *argv[])
  130.25 +{
  130.26 +#ifdef USE_OPENAL
  130.27 +        alutInit(0,0);
  130.28 +//        printf("AlutInit\n");
  130.29 +        atexit(closeal);
  130.30 +//        printf("AlutInit\n");
  130.31 +#endif
  130.32 +}
  130.33 +
  130.34 +void closeal()
  130.35 +{
  130.36 +#ifdef USE_OPENAL
  130.37 +        alutExit();
  130.38 +#endif
  130.39 +}
  130.40 +
  130.41 +void check()
  130.42 +{
  130.43 +#ifdef USE_OPENAL
  130.44 +        ALenum error;
  130.45 +        if ((error = alGetError()) != AL_NO_ERROR)
  130.46 +        {
  130.47 +//                printf("Error : %08X\n", error);
  130.48 +//                exit(-1);
  130.49 +        }
  130.50 +#endif
  130.51 +}
  130.52 +
  130.53 +void inital()
  130.54 +{
  130.55 +#ifdef USE_OPENAL
  130.56 +        int c;
  130.57 +        int16_t buf[BUFLEN*2];
  130.58 +        format = AL_FORMAT_STEREO16;
  130.59 +//        printf("1\n");
  130.60 +        check();
  130.61 +
  130.62 +//        printf("2\n");
  130.63 +        alGenBuffers(4, buffers);
  130.64 +        check();
  130.65 +        
  130.66 +//        printf("3\n");
  130.67 +        alGenSources(1, &source);
  130.68 +        check();
  130.69 +
  130.70 +//        printf("4\n");
  130.71 +        alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
  130.72 +        alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
  130.73 +        alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
  130.74 +        alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
  130.75 +        alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
  130.76 +        check();
  130.77 +
  130.78 +        memset(buf,0,BUFLEN*4);
  130.79 +
  130.80 +//        printf("5\n");
  130.81 +        for (c=0;c<4;c++)
  130.82 +            alBufferData(buffers[c], AL_FORMAT_STEREO16, buf, BUFLEN*2*2, FREQ);
  130.83 +        alSourceQueueBuffers(source, 4, buffers);
  130.84 +        check();
  130.85 +//        printf("6 %08X\n",source);
  130.86 +        alSourcePlay(source);
  130.87 +        check();
  130.88 +//        printf("InitAL!!! %08X\n",source);
  130.89 +#endif
  130.90 +}
  130.91 +
  130.92 +void givealbuffer(int16_t *buf)
  130.93 +{
  130.94 +#ifdef USE_OPENAL
  130.95 +        int processed;
  130.96 +        int state;
  130.97 +        int c;
  130.98 +        
  130.99 +        //return;
 130.100 +        
 130.101 +//        printf("Start\n");
 130.102 +        check();
 130.103 +        
 130.104 +//        printf("GiveALBuffer %08X\n",source);
 130.105 +        
 130.106 +        alGetSourcei(source, AL_SOURCE_STATE, &state);
 130.107 +
 130.108 +        check();
 130.109 +        
 130.110 +        if (state==0x1014)
 130.111 +        {
 130.112 +                alSourcePlay(source);
 130.113 +//                printf("Resetting sound\n");
 130.114 +        }
 130.115 +//        printf("State - %i %08X\n",state,state);
 130.116 +        alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
 130.117 +
 130.118 +//        printf("P ");
 130.119 +        check();
 130.120 +//        printf("Processed - %i\n",processed);
 130.121 +
 130.122 +        if (processed>=1)
 130.123 +        {
 130.124 +                ALuint buffer;
 130.125 +
 130.126 +                alSourceUnqueueBuffers(source, 1, &buffer);
 130.127 +//                printf("U ");
 130.128 +                check();
 130.129 +
 130.130 +//                for (c=0;c<BUFLEN*2;c++) buf[c]^=0x8000;
 130.131 +                alBufferData(buffer, AL_FORMAT_STEREO16, buf, BUFLEN*2*2, FREQ);
 130.132 +//                printf("B ");
 130.133 +               check();
 130.134 +
 130.135 +                alSourceQueueBuffers(source, 1, &buffer);
 130.136 +//                printf("Q ");
 130.137 +                check();
 130.138 +                
 130.139 +//                printf("\n");
 130.140 +
 130.141 +//                if (!allog) allog=fopen("al.pcm","wb");
 130.142 +//                fwrite(buf,BUFLEN*2,1,allog);
 130.143 +        }
 130.144 +//        printf("\n");
 130.145 +#endif
 130.146 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/src/um8881f.c	Sun Apr 21 14:54:35 2013 +0100
   131.3 @@ -0,0 +1,70 @@
   131.4 +#include "ibm.h"
   131.5 +#include "io.h"
   131.6 +#include "mem.h"
   131.7 +
   131.8 +#include "um8881f.h"
   131.9 +
  131.10 +static uint8_t card_16[256];
  131.11 +static uint8_t card_18[256];
  131.12 +
  131.13 +void um8881f_write(int func, int addr, uint8_t val)
  131.14 +{
  131.15 +        if (addr == 0x54)
  131.16 +        {
  131.17 +                if ((card_16[0x54] ^ val) & 0x01)
  131.18 +                {
  131.19 +                        if (val & 1)
  131.20 +                           mem_sethandler(0xe0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml);
  131.21 +                        else
  131.22 +                           mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   NULL,          NULL,           NULL          );
  131.23 +                }
  131.24 +                flushmmucache_nopc();
  131.25 +        }
  131.26 +        if (addr == 0x55)
  131.27 +        {
  131.28 +                if ((card_16[0x55] ^ val) & 0xc0)
  131.29 +                {
  131.30 +                        switch (val & 0xc0)
  131.31 +                        {
  131.32 +                                case 0x00: mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   mem_write_ram, mem_write_ramw, mem_write_raml); break;
  131.33 +                                case 0x40: mem_sethandler(0xf0000, 0x10000, mem_read_bios,   mem_read_biosw,   mem_read_biosl,   NULL,          NULL,           NULL          ); break;
  131.34 +                                case 0x80: mem_sethandler(0xf0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    mem_write_ram, mem_write_ramw, mem_write_raml); break;
  131.35 +                                case 0xc0: mem_sethandler(0xf0000, 0x10000, mem_read_ram,    mem_read_ramw,    mem_read_raml,    NULL,          NULL,           NULL          ); break;
  131.36 +                        }
  131.37 +                        shadowbios = val & 0x80;
  131.38 +                        shadowbios_write = !(val & 0x40);
  131.39 +                        flushmmucache_nopc();
  131.40 +                }
  131.41 +        }
  131.42 +        if (addr >= 4) 
  131.43 +           card_16[addr] = val;
  131.44 +}
  131.45 +
  131.46 +uint8_t um8881f_read(int func, int addr)
  131.47 +{
  131.48 +        return card_16[addr];
  131.49 +}
  131.50 + 
  131.51 +void um8886f_write(int func, int addr, uint8_t val)
  131.52 +{
  131.53 +        if (addr >= 4) 
  131.54 +           card_18[addr] = val;
  131.55 +}
  131.56 +
  131.57 +uint8_t um8886f_read(int func, int addr)
  131.58 +{
  131.59 +        return card_18[addr];
  131.60 +}
  131.61 + 
  131.62 + 
  131.63 +     
  131.64 +void um8881f_init()
  131.65 +{
  131.66 +        pci_add_specific(16, um8881f_read, um8881f_write);
  131.67 +        pci_add_specific(18, um8886f_read, um8886f_write);
  131.68 +        
  131.69 +        card_16[0] = card_18[0] = 0x60; /*UMC*/
  131.70 +        card_16[1] = card_18[1] = 0x10;
  131.71 +        card_16[2] = 0x81; card_16[3] = 0x88; /*UM8881 Host - PCI bridge*/
  131.72 +        card_18[2] = 0x86; card_18[3] = 0x88; /*UM8886 PCI - ISA bridge*/
  131.73 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/src/um8881f.h	Sun Apr 21 14:54:35 2013 +0100
   132.3 @@ -0,0 +1,1 @@
   132.4 +void um8881f_init();
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/src/vid_cga.c	Sun Apr 21 14:54:35 2013 +0100
   133.3 @@ -0,0 +1,494 @@
   133.4 +/*CGA emulation*/
   133.5 +#include "ibm.h"
   133.6 +#include "video.h"
   133.7 +
   133.8 +void cga_out(uint16_t addr, uint8_t val)
   133.9 +{
  133.10 +        uint8_t old;
  133.11 +//        pclog("CGA_OUT %04X %02X\n", addr, val);
  133.12 +        switch (addr)
  133.13 +        {
  133.14 +                case 0x3D4:
  133.15 +                crtcreg=val&31;
  133.16 +                return;
  133.17 +                case 0x3D5:
  133.18 +                old=crtc[crtcreg];
  133.19 +                crtc[crtcreg]=val&crtcmask[crtcreg];
  133.20 +                if (old!=val)
  133.21 +                {
  133.22 +                        if (crtcreg<0xE || crtcreg>0x10)
  133.23 +                        {
  133.24 +                                fullchange=changeframecount;
  133.25 +                                cga_recalctimings();
  133.26 +                        }
  133.27 +                }
  133.28 +                return;
  133.29 +                case 0x3D8:
  133.30 +                cgamode=val;
  133.31 +                return;
  133.32 +                case 0x3D9:
  133.33 +                cgacol=val;
  133.34 +                return;
  133.35 +        }
  133.36 +}
  133.37 +
  133.38 +uint8_t cga_in(uint16_t addr)
  133.39 +{
  133.40 +//        pclog("CGA_IN %04X\n", addr);
  133.41 +        switch (addr)
  133.42 +        {
  133.43 +                case 0x3D4:
  133.44 +                return crtcreg;
  133.45 +                case 0x3D5:
  133.46 +                return crtc[crtcreg];
  133.47 +                case 0x3DA:
  133.48 +                return cgastat;
  133.49 +        }
  133.50 +        return 0xFF;
  133.51 +}
  133.52 +
  133.53 +extern uint8_t charbuffer[256];
  133.54 +
  133.55 +void cga_write(uint32_t addr, uint8_t val)
  133.56 +{
  133.57 +//        pclog("CGA_WRITE %04X %02X\n", addr, val);
  133.58 +        vram[addr&0x3FFF]=val;
  133.59 +        charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = val;
  133.60 +        charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val;
  133.61 +        cycles -= 4;
  133.62 +}
  133.63 +
  133.64 +uint8_t cga_read(uint32_t addr)
  133.65 +{
  133.66 +        cycles -= 4;        
  133.67 +        charbuffer[ ((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc] = vram[addr&0x3FFF];
  133.68 +        charbuffer[(((int)(((dispontime - vidtime) * 2) / CGACONST)) & 0xfc) | 1] = vram[addr&0x3FFF];
  133.69 +//        pclog("CGA_READ %04X\n", addr);
  133.70 +        return vram[addr&0x3FFF];
  133.71 +}
  133.72 +
  133.73 +void cga_recalctimings()
  133.74 +{
  133.75 +        pclog("Recalc - %i %i %i\n", crtc[0], crtc[1], cgamode & 1);
  133.76 +        if (cgamode&1)
  133.77 +        {
  133.78 +                disptime=crtc[0]+1;
  133.79 +                dispontime=crtc[1];
  133.80 +        }
  133.81 +        else
  133.82 +        {
  133.83 +                disptime=(crtc[0]+1)<<1;
  133.84 +                dispontime=crtc[1]<<1;
  133.85 +        }
  133.86 +        dispofftime=disptime-dispontime;
  133.87 +//        printf("%i %f %f %f  %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
  133.88 +        dispontime*=CGACONST;
  133.89 +        dispofftime*=CGACONST;
  133.90 +//        printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
  133.91 +}
  133.92 +
  133.93 +static int linepos,displine;
  133.94 +static int sc,vc;
  133.95 +static int cgadispon;
  133.96 +static int con,coff,cursoron,cgablink;
  133.97 +static int vsynctime,vadj;
  133.98 +static uint16_t ma,maback,ca;
  133.99 +static int oddeven = 0;
 133.100 +
 133.101 +static int ntsc_col[8][8]=
 133.102 +{
 133.103 +        {0,0,0,0,0,0,0,0}, /*Black*/
 133.104 +        {0,0,1,1,1,1,0,0}, /*Blue*/
 133.105 +        {1,0,0,0,0,1,1,1}, /*Green*/
 133.106 +        {0,0,0,0,1,1,1,1}, /*Cyan*/
 133.107 +        {1,1,1,1,0,0,0,0}, /*Red*/
 133.108 +        {0,1,1,1,1,0,0,0}, /*Magenta*/
 133.109 +        {1,1,0,0,0,0,1,1}, /*Yellow*/
 133.110 +        {1,1,1,1,1,1,1,1}  /*White*/
 133.111 +};
 133.112 +
 133.113 +int i_filt[8],q_filt[8];
 133.114 +
 133.115 +
 133.116 +void cga_poll()
 133.117 +{
 133.118 +        uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
 133.119 +        int drawcursor;
 133.120 +        int x,c;
 133.121 +        int oldvc;
 133.122 +        uint8_t chr,attr;
 133.123 +        uint16_t dat,dat2,dat3,dat4;
 133.124 +        int cols[4];
 133.125 +        int col;
 133.126 +        int oldsc;
 133.127 +        int y_buf[8]={0,0,0,0,0,0,0,0},y_val,y_tot;
 133.128 +        int i_buf[8]={0,0,0,0,0,0,0,0},i_val,i_tot;
 133.129 +        int q_buf[8]={0,0,0,0,0,0,0,0},q_val,q_tot;
 133.130 +        int r,g,b;
 133.131 +        if (!linepos)
 133.132 +        {
 133.133 +                vidtime+=dispofftime;
 133.134 +                cgastat|=1;
 133.135 +                linepos=1;
 133.136 +                oldsc=sc;
 133.137 +                if ((crtc[8] & 3) == 3) 
 133.138 +                   sc = ((sc << 1) + oddeven) & 7;
 133.139 +                if (cgadispon)
 133.140 +                {
 133.141 +                        if (displine<firstline)
 133.142 +                        {
 133.143 +                                firstline=displine;
 133.144 +//                                printf("Firstline %i\n",firstline);
 133.145 +                        }
 133.146 +                        lastline=displine;
 133.147 +                        for (c=0;c<8;c++)
 133.148 +                        {
 133.149 +                                if ((cgamode&0x12)==0x12)
 133.150 +                                {
 133.151 +                                        buffer->line[displine][c]=0;
 133.152 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
 133.153 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=0;
 133.154 +                                }
 133.155 +                                else
 133.156 +                                {
 133.157 +                                        buffer->line[displine][c]=(cgacol&15)+16;
 133.158 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
 133.159 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
 133.160 +                                }
 133.161 +                        }
 133.162 +                        if (cgamode&1)
 133.163 +                        {
 133.164 +                                for (x=0;x<crtc[1];x++)
 133.165 +                                {
 133.166 +                                        chr=charbuffer[x<<1];
 133.167 +                                        attr=charbuffer[(x<<1)+1];
 133.168 +                                        drawcursor=((ma==ca) && con && cursoron);
 133.169 +                                        if (cgamode&0x20)
 133.170 +                                        {
 133.171 +                                                cols[1]=(attr&15)+16;
 133.172 +                                                cols[0]=((attr>>4)&7)+16;
 133.173 +                                                if ((cgablink&8) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
 133.174 +                                        }
 133.175 +                                        else
 133.176 +                                        {
 133.177 +                                                cols[1]=(attr&15)+16;
 133.178 +                                                cols[0]=(attr>>4)+16;
 133.179 +                                        }
 133.180 +                                        if (drawcursor)
 133.181 +                                        {
 133.182 +                                                for (c=0;c<8;c++)
 133.183 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
 133.184 +                                        }
 133.185 +                                        else
 133.186 +                                        {
 133.187 +                                                for (c=0;c<8;c++)
 133.188 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 133.189 +                                        }
 133.190 +                                        ma++;
 133.191 +                                }
 133.192 +                        }
 133.193 +                        else if (!(cgamode&2))
 133.194 +                        {
 133.195 +                                for (x=0;x<crtc[1];x++)
 133.196 +                                {
 133.197 +                                        chr=vram[((ma<<1)&0x3FFF)];
 133.198 +                                        attr=vram[(((ma<<1)+1)&0x3FFF)];
 133.199 +                                        drawcursor=((ma==ca) && con && cursoron);
 133.200 +                                        if (cgamode&0x20)
 133.201 +                                        {
 133.202 +                                                cols[1]=(attr&15)+16;
 133.203 +                                                cols[0]=((attr>>4)&7)+16;
 133.204 +                                                if ((cgablink&8) && (attr&0x80)) cols[1]=cols[0];
 133.205 +                                        }
 133.206 +                                        else
 133.207 +                                        {
 133.208 +                                                cols[1]=(attr&15)+16;
 133.209 +                                                cols[0]=(attr>>4)+16;
 133.210 +                                        }
 133.211 +                                        ma++;
 133.212 +                                        if (drawcursor)
 133.213 +                                        {
 133.214 +                                                for (c=0;c<8;c++)
 133.215 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
 133.216 +                                        }
 133.217 +                                        else
 133.218 +                                        {
 133.219 +                                                for (c=0;c<8;c++)
 133.220 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 133.221 +                                        }
 133.222 +                                }
 133.223 +                        }
 133.224 +                        else if (!(cgamode&16))
 133.225 +                        {
 133.226 +                                cols[0]=(cgacol&15)|16;
 133.227 +                                col=(cgacol&16)?24:16;
 133.228 +                                if (cgamode&4)
 133.229 +                                {
 133.230 +                                        cols[1]=col|3;
 133.231 +                                        cols[2]=col|4;
 133.232 +                                        cols[3]=col|7;
 133.233 +                                }
 133.234 +                                else if (cgacol&32)
 133.235 +                                {
 133.236 +                                        cols[1]=col|3;
 133.237 +                                        cols[2]=col|5;
 133.238 +                                        cols[3]=col|7;
 133.239 +                                }
 133.240 +                                else
 133.241 +                                {
 133.242 +                                        cols[1]=col|2;
 133.243 +                                        cols[2]=col|4;
 133.244 +                                        cols[3]=col|6;
 133.245 +                                }
 133.246 +                                for (x=0;x<crtc[1];x++)
 133.247 +                                {
 133.248 +                                        dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
 133.249 +                                        ma++;
 133.250 +                                        for (c=0;c<8;c++)
 133.251 +                                        {
 133.252 +                                                buffer->line[displine][(x<<4)+(c<<1)+8]=
 133.253 +                                                  buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
 133.254 +                                                dat<<=2;
 133.255 +                                        }
 133.256 +                                }
 133.257 +                        }
 133.258 +                        else
 133.259 +                        {
 133.260 +                                cols[0]=0; cols[1]=(cgacol&15)+16;
 133.261 +                                for (x=0;x<crtc[1];x++)
 133.262 +                                {
 133.263 +                                        dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
 133.264 +                                        ma++;
 133.265 +                                        for (c=0;c<16;c++)
 133.266 +                                        {
 133.267 +                                                buffer->line[displine][(x<<4)+c+8]=cols[dat>>15];
 133.268 +                                                dat<<=1;
 133.269 +                                        }
 133.270 +                                }
 133.271 +                        }
 133.272 +                }
 133.273 +                else
 133.274 +                {
 133.275 +                        cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
 133.276 +                        if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
 133.277 +                        else           hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
 133.278 +                }
 133.279 +
 133.280 +                if (cgamode&1) x=(crtc[1]<<3)+16;
 133.281 +                else           x=(crtc[1]<<4)+16;
 133.282 +                if (cga_comp)
 133.283 +                {
 133.284 +                        for (c=0;c<x;c++)
 133.285 +                        {
 133.286 +                                y_buf[(c<<1)&6]=ntsc_col[buffer->line[displine][c]&7][(c<<1)&6]?0x6000:0;
 133.287 +                                y_buf[(c<<1)&6]+=(buffer->line[displine][c]&8)?0x3000:0;
 133.288 +                                i_buf[(c<<1)&6]=y_buf[(c<<1)&6]*i_filt[(c<<1)&6];
 133.289 +                                q_buf[(c<<1)&6]=y_buf[(c<<1)&6]*q_filt[(c<<1)&6];
 133.290 +                                y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
 133.291 +                                i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
 133.292 +                                q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
 133.293 +
 133.294 +                                y_val=y_tot>>10;
 133.295 +                                if (y_val>255) y_val=255;
 133.296 +                                y_val<<=16;
 133.297 +                                i_val=i_tot>>12;
 133.298 +                                if (i_val>39041) i_val=39041;
 133.299 +                                if (i_val<-39041) i_val=-39041;
 133.300 +                                q_val=q_tot>>12;
 133.301 +                                if (q_val>34249) q_val=34249;
 133.302 +                                if (q_val<-34249) q_val=-34249;
 133.303 +
 133.304 +                                r=(y_val+249*i_val+159*q_val)>>16;
 133.305 +                                g=(y_val-70*i_val-166*q_val)>>16;
 133.306 +                                b=(y_val-283*i_val+436*q_val)>>16;
 133.307 +
 133.308 +                                y_buf[((c<<1)&6)+1]=ntsc_col[buffer->line[displine][c]&7][((c<<1)&6)+1]?0x6000:0;
 133.309 +                                y_buf[((c<<1)&6)+1]+=(buffer->line[displine][c]&8)?0x3000:0;
 133.310 +                                i_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*i_filt[((c<<1)&6)+1];
 133.311 +                                q_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*q_filt[((c<<1)&6)+1];
 133.312 +                                y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
 133.313 +                                i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
 133.314 +                                q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
 133.315 +
 133.316 +                                y_val=y_tot>>10;
 133.317 +                                if (y_val>255) y_val=255;
 133.318 +                                y_val<<=16;
 133.319 +                                i_val=i_tot>>12;
 133.320 +                                if (i_val>39041) i_val=39041;
 133.321 +                                if (i_val<-39041) i_val=-39041;
 133.322 +                                q_val=q_tot>>12;
 133.323 +                                if (q_val>34249) q_val=34249;
 133.324 +                                if (q_val<-34249) q_val=-34249;
 133.325 +
 133.326 +                                r+=(y_val+249*i_val+159*q_val)>>16;
 133.327 +                                g+=(y_val-70*i_val-166*q_val)>>16;
 133.328 +                                b+=(y_val-283*i_val+436*q_val)>>16;
 133.329 +                                if (r>511) r=511;
 133.330 +                                if (g>511) g=511;
 133.331 +                                if (b>511) b=511;
 133.332 +
 133.333 +                                ((uint32_t *)buffer32->line[displine])[c]=makecol32(r/2,g/2,b/2);
 133.334 +                        }
 133.335 +                }
 133.336 +
 133.337 +                sc=oldsc;
 133.338 +                if (vc==crtc[7] && !sc)
 133.339 +                   cgastat|=8;
 133.340 +                displine++;
 133.341 +                if (displine>=360) displine=0;
 133.342 +        }
 133.343 +        else
 133.344 +        {
 133.345 +                vidtime+=dispontime;
 133.346 +                if (cgadispon) cgastat&=~1;
 133.347 +                linepos=0;
 133.348 +                if (vsynctime)
 133.349 +                {
 133.350 +                        vsynctime--;
 133.351 +                        if (!vsynctime)
 133.352 +                           cgastat&=~8;
 133.353 +                }
 133.354 +                if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; }
 133.355 +                if ((crtc[8] & 3) == 3 && sc == (crtc[9] >> 1))
 133.356 +                   maback = ma;
 133.357 +                if (vadj)
 133.358 +                {
 133.359 +                        sc++;
 133.360 +                        sc&=31;
 133.361 +                        ma=maback;
 133.362 +                        vadj--;
 133.363 +                        if (!vadj)
 133.364 +                        {
 133.365 +                                cgadispon=1;
 133.366 +                                ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 133.367 +                                sc=0;
 133.368 +                        }
 133.369 +                }
 133.370 +                else if (sc==crtc[9])
 133.371 +                {
 133.372 +                        maback=ma;
 133.373 +                        sc=0;
 133.374 +                        oldvc=vc;
 133.375 +                        vc++;
 133.376 +                        vc&=127;
 133.377 +
 133.378 +                        if (vc==crtc[6]) cgadispon=0;
 133.379 +
 133.380 +                        if (oldvc==crtc[4])
 133.381 +                        {
 133.382 +                                vc=0;
 133.383 +                                vadj=crtc[5];
 133.384 +                                if (!vadj) cgadispon=1;
 133.385 +                                if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 133.386 +                                if ((crtc[10]&0x60)==0x20) cursoron=0;
 133.387 +                                else                       cursoron=cgablink&8;
 133.388 +                        }
 133.389 +
 133.390 +                        if (vc==crtc[7])
 133.391 +                        {
 133.392 +                                cgadispon=0;
 133.393 +                                displine=0;
 133.394 +                                vsynctime=(crtc[3]>>4)+1;
 133.395 +                                if (crtc[7])
 133.396 +                                {
 133.397 +                                        if (cgamode&1) x=(crtc[1]<<3)+16;
 133.398 +                                        else           x=(crtc[1]<<4)+16;
 133.399 +                                        lastline++;
 133.400 +                                        if (x!=xsize || (lastline-firstline)!=ysize)
 133.401 +                                        {
 133.402 +                                                xsize=x;
 133.403 +                                                ysize=lastline-firstline;
 133.404 +                                                if (xsize<64) xsize=656;
 133.405 +                                                if (ysize<32) ysize=200;
 133.406 +                                                updatewindowsize(xsize,(ysize<<1)+16);
 133.407 +                                        }
 133.408 +                                        
 133.409 +startblit();
 133.410 +                                        if (cga_comp) 
 133.411 +                                           video_blit_memtoscreen(0, firstline-4, 0, (lastline-firstline)+8, xsize, (lastline-firstline)+8);
 133.412 +                                        else          
 133.413 +                                           video_blit_memtoscreen_8(0, firstline-4, xsize, (lastline-firstline)+8);
 133.414 +                                        if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
 133.415 +                                        readflash=0;
 133.416 +                                        frames++;
 133.417 +endblit();
 133.418 +                                        video_res_x = xsize - 16;
 133.419 +                                        video_res_y = ysize;
 133.420 +                                        if (cgamode & 1)
 133.421 +                                        {
 133.422 +                                                video_res_x /= 8;
 133.423 +                                                video_res_y /= crtc[9] + 1;
 133.424 +                                                video_bpp = 0;
 133.425 +                                        }
 133.426 +                                        else if (!(cgamode & 2))
 133.427 +                                        {
 133.428 +                                                video_res_x /= 16;
 133.429 +                                                video_res_y /= crtc[9] + 1;
 133.430 +                                                video_bpp = 0;
 133.431 +                                        }
 133.432 +                                        else if (!(cgamode&16))
 133.433 +                                        {
 133.434 +                                                video_res_x /= 2;
 133.435 +                                                video_bpp = 2;
 133.436 +                                        }
 133.437 +                                        else
 133.438 +                                        {
 133.439 +                                                video_bpp = 1;
 133.440 +                                        }
 133.441 +                                }
 133.442 +                                firstline=1000;
 133.443 +                                lastline=0;
 133.444 +                                cgablink++;
 133.445 +                                oddeven ^= 1;
 133.446 +                        }
 133.447 +                }
 133.448 +                else
 133.449 +                {
 133.450 +                        sc++;
 133.451 +                        sc&=31;
 133.452 +                        ma=maback;
 133.453 +                }
 133.454 +                if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1;
 133.455 +                if (cgadispon && (cgamode&1))
 133.456 +                {
 133.457 +                        for (x=0;x<(crtc[1]<<1);x++)
 133.458 +                            charbuffer[x]=vram[(((ma<<1)+x)&0x3FFF)];
 133.459 +                }
 133.460 +        }
 133.461 +}
 133.462 +
 133.463 +
 133.464 +int cga_init()
 133.465 +{
 133.466 +        int c;
 133.467 +        int cga_tint = -2;
 133.468 +        for (c=0;c<8;c++)
 133.469 +        {
 133.470 +                i_filt[c]=512.0*cos((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
 133.471 +                q_filt[c]=512.0*sin((3.14*(cga_tint+c*4)/16.0) - 33.0/180.0);
 133.472 +        }
 133.473 +        mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL);
 133.474 +        return 0;
 133.475 +}
 133.476 +
 133.477 +GFXCARD vid_cga =
 133.478 +{
 133.479 +        cga_init,
 133.480 +        /*IO at 3Cx/3Dx*/
 133.481 +        cga_out,
 133.482 +        cga_in,
 133.483 +        /*IO at 3Ax/3Bx*/
 133.484 +        video_out_null,
 133.485 +        video_in_null,
 133.486 +
 133.487 +        cga_poll,
 133.488 +        cga_recalctimings,
 133.489 +
 133.490 +        video_write_null,
 133.491 +        video_write_null,
 133.492 +        cga_write,
 133.493 +
 133.494 +        video_read_null,
 133.495 +        video_read_null,
 133.496 +        cga_read
 133.497 +};
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/src/vid_cga.h	Sun Apr 21 14:54:35 2013 +0100
   134.3 @@ -0,0 +1,7 @@
   134.4 +int     cga_init();
   134.5 +void    cga_out(uint16_t addr, uint8_t val);
   134.6 +uint8_t cga_in(uint16_t addr);
   134.7 +void    cga_poll();
   134.8 +void    cga_write(uint32_t addr, uint8_t val);
   134.9 +uint8_t cga_read(uint32_t addr);
  134.10 +void    cga_recalctimings();
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/src/vid_ega.c	Sun Apr 21 14:54:35 2013 +0100
   135.3 @@ -0,0 +1,720 @@
   135.4 +/*EGA emulation*/
   135.5 +#include "ibm.h"
   135.6 +#include "video.h"
   135.7 +
   135.8 +void    ega_recalctimings();
   135.9 +void    ega_write(uint32_t addr, uint8_t val);
  135.10 +uint8_t ega_read(uint32_t addr);
  135.11 +
  135.12 +extern uint8_t edatlookup[4][4];
  135.13 +
  135.14 +uint8_t ega_3c2;
  135.15 +
  135.16 +static uint8_t la, lb, lc, ld;
  135.17 +static uint8_t ega_rotate[8][256];
  135.18 +
  135.19 +/*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/
  135.20 +int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/
  135.21 +
  135.22 +void ega_out(uint16_t addr, uint8_t val)
  135.23 +{
  135.24 +        int c;
  135.25 +        uint8_t o,old;
  135.26 +        if ((addr&0xFFF0) == 0x3B0) addr |= 0x20;
  135.27 +        switch (addr)
  135.28 +        {
  135.29 +                case 0x3C0:
  135.30 +                if (!attrff)
  135.31 +                   attraddr=val&31;
  135.32 +                else
  135.33 +                {
  135.34 +                        attrregs[attraddr&31]=val;
  135.35 +                        if (attraddr<16) fullchange=changeframecount;
  135.36 +                        if (attraddr==0x10 || attraddr==0x14 || attraddr<0x10)
  135.37 +                        {
  135.38 +                                for (c=0;c<16;c++)
  135.39 +                                {
  135.40 +                                        if (attrregs[0x10]&0x80) egapal[c]=(attrregs[c]&0xF)|((attrregs[0x14]&0xF)<<4);
  135.41 +                                        else                     egapal[c]=(attrregs[c]&0x3F)|((attrregs[0x14]&0xC)<<4);
  135.42 +                                }
  135.43 +                        }
  135.44 +                }
  135.45 +                attrff^=1;
  135.46 +                break;
  135.47 +                case 0x3C2:
  135.48 +                egaswitchread=val&0xC;
  135.49 +                vres=!(val&0x80);
  135.50 +                pallook=(vres)?pallook16:pallook64;
  135.51 +                vidclock=val&4; /*printf("3C2 write %02X\n",val);*/
  135.52 +                ega_3c2=val;
  135.53 +                break;
  135.54 +                case 0x3C4: seqaddr=val; break;
  135.55 +                case 0x3C5:
  135.56 +                o=seqregs[seqaddr&0xF];
  135.57 +                seqregs[seqaddr&0xF]=val;
  135.58 +                if (o!=val && (seqaddr&0xF)==1) ega_recalctimings();
  135.59 +                switch (seqaddr&0xF)
  135.60 +                {
  135.61 +                        case 1: if (scrblank && !(val&0x20)) fullchange=3; scrblank=(scrblank&~0x20)|(val&0x20); break;
  135.62 +                        case 2: writemask=val&0xF; break;
  135.63 +                        case 3:
  135.64 +                        charset=val&0xF;
  135.65 +                        charseta=((charset>>2)*0x10000)+2;
  135.66 +                        charsetb=((charset&3) *0x10000)+2;
  135.67 +                        break;
  135.68 +                }
  135.69 +                break;
  135.70 +                case 0x3CE: gdcaddr=val; break;
  135.71 +                case 0x3CF:
  135.72 +                gdcreg[gdcaddr&15]=val;
  135.73 +                switch (gdcaddr&15)
  135.74 +                {
  135.75 +                        case 2: colourcompare=val; break;
  135.76 +                        case 4: readplane=val&3; break;
  135.77 +                        case 5: writemode=val&3; readmode=val&8; break;
  135.78 +                        case 6:
  135.79 +                        mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  135.80 +//                                pclog("Write mapping %02X\n", val);
  135.81 +                        switch (val&0xC)
  135.82 +                        {
  135.83 +                                case 0x0: /*128k at A0000*/
  135.84 +                                mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  135.85 +                                break;
  135.86 +                                case 0x4: /*64k at A0000*/
  135.87 +                                mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  135.88 +                                break;
  135.89 +                                case 0x8: /*32k at B0000*/
  135.90 +                                mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  135.91 +                                break;
  135.92 +                                case 0xC: /*32k at B8000*/
  135.93 +                                mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  135.94 +                                break;
  135.95 +                        }
  135.96 +
  135.97 +                        break;
  135.98 +                        case 7: colournocare=val; break;
  135.99 +                }
 135.100 +                break;
 135.101 +                case 0x3D4:
 135.102 +                crtcreg=val;
 135.103 +                return;
 135.104 +                case 0x3D5:
 135.105 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
 135.106 +                old=crtc[crtcreg];
 135.107 +                crtc[crtcreg]=val;
 135.108 +                if (old!=val)
 135.109 +                {
 135.110 +                        if (crtcreg<0xE || crtcreg>0x10)
 135.111 +                        {
 135.112 +                                fullchange=changeframecount;
 135.113 +                                ega_recalctimings();
 135.114 +                        }
 135.115 +                }
 135.116 +                break;
 135.117 +        }
 135.118 +}
 135.119 +
 135.120 +uint8_t ega_in(uint16_t addr)
 135.121 +{
 135.122 +        uint8_t temp;
 135.123 +        if ((addr&0xFFF0) == 0x3B0) addr |= 0x20;
 135.124 +        switch (addr)
 135.125 +        {
 135.126 +                case 0x3C0: return attraddr;
 135.127 +                case 0x3C1: return attrregs[attraddr];
 135.128 +                case 0x3C2:
 135.129 +//                printf("Read egaswitch %02X %02X %i\n",egaswitchread,egaswitches,VGA);
 135.130 +                switch (egaswitchread)
 135.131 +                {
 135.132 +                        case 0xC: return (egaswitches&1)?0x10:0;
 135.133 +                        case 0x8: return (egaswitches&2)?0x10:0;
 135.134 +                        case 0x4: return (egaswitches&4)?0x10:0;
 135.135 +                        case 0x0: return (egaswitches&8)?0x10:0;
 135.136 +                }
 135.137 +                break;
 135.138 +                case 0x3C4: return seqaddr;
 135.139 +                case 0x3C5:
 135.140 +                return seqregs[seqaddr&0xF];
 135.141 +                case 0x3CE: return gdcaddr;
 135.142 +                case 0x3CF:
 135.143 +                return gdcreg[gdcaddr&0xF];
 135.144 +                case 0x3D4:
 135.145 +                return crtcreg;
 135.146 +                case 0x3D5:
 135.147 +                return crtc[crtcreg];
 135.148 +                case 0x3DA:
 135.149 +                attrff=0;
 135.150 +                cgastat^=0x30; /*Fools IBM EGA video BIOS self-test*/
 135.151 +                return cgastat;
 135.152 +        }
 135.153 +//        printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
 135.154 +        return 0xFF;
 135.155 +}
 135.156 +
 135.157 +static int linepos,displine,vslines;
 135.158 +static int egadispon;
 135.159 +static uint32_t ma,ca,maback;
 135.160 +static int vc,sc;
 135.161 +static int con,cursoron,cgablink;
 135.162 +static int scrollcache;
 135.163 +#define vrammask 0x3FFFF
 135.164 +
 135.165 +void ega_recalctimings()
 135.166 +{
 135.167 +        float crtcconst;
 135.168 +        int temp;
 135.169 +        ega_vtotal=crtc[6];
 135.170 +        ega_dispend=crtc[0x12];
 135.171 +        ega_vsyncstart=crtc[0x10];
 135.172 +        ega_split=crtc[0x18];
 135.173 +
 135.174 +        if (crtc[7]&1) ega_vtotal|=0x100;
 135.175 +        if (crtc[7]&32) ega_vtotal|=0x200;
 135.176 +        ega_vtotal++;
 135.177 +
 135.178 +        if (crtc[7]&2) ega_dispend|=0x100;
 135.179 +        if (crtc[7]&64) ega_dispend|=0x200;
 135.180 +        ega_dispend++;
 135.181 +
 135.182 +        if (crtc[7]&4) ega_vsyncstart|=0x100;
 135.183 +        if (crtc[7]&128) ega_vsyncstart|=0x200;
 135.184 +        ega_vsyncstart++;
 135.185 +
 135.186 +        if (crtc[7]&0x10)    ega_split|=0x100;
 135.187 +        if (crtc[9]&0x40)    ega_split|=0x200;
 135.188 +        ega_split+=2;
 135.189 +
 135.190 +        ega_hdisp=crtc[1];
 135.191 +        ega_hdisp++;
 135.192 +
 135.193 +        ega_rowoffset=crtc[0x13];
 135.194 +
 135.195 +        printf("Recalc! %i %i %i %i   %i %02X\n",ega_vtotal,ega_dispend,ega_vsyncstart,ega_split,ega_hdisp,attrregs[0x16]);
 135.196 +
 135.197 +        if (vidclock) crtcconst=(seqregs[1]&1)?(MDACONST*(8.0/9.0)):MDACONST;
 135.198 +        else          crtcconst=(seqregs[1]&1)?(CGACONST*(8.0/9.0)):CGACONST;
 135.199 +
 135.200 +        disptime=crtc[0]+2;
 135.201 +        dispontime=crtc[1]+1;
 135.202 +
 135.203 +        printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
 135.204 +        if (seqregs[1]&8) { disptime*=2; dispontime*=2; }
 135.205 +        dispofftime=disptime-dispontime;
 135.206 +        dispontime*=crtcconst;
 135.207 +        dispofftime*=crtcconst;
 135.208 +
 135.209 +
 135.210 +//        printf("EGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4));
 135.211 +//        printf("EGA vert total %i display end %i max row %i vsync %i\n",ega_vtotal,ega_dispend,(crtc[9]&31)+1,ega_vsyncstart);
 135.212 +//        printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*ega_vtotal,(dispontime+dispofftime)*ega_vtotal*70,seqregs[1]);
 135.213 +}
 135.214 +
 135.215 +void ega_poll()
 135.216 +{
 135.217 +        uint8_t chr,dat,attr;
 135.218 +        uint32_t charaddr;
 135.219 +        int x,xx;
 135.220 +        uint32_t fg,bg;
 135.221 +        int offset;
 135.222 +        uint8_t edat[4];
 135.223 +        int drawcursor=0;
 135.224 +
 135.225 +        if (!linepos)
 135.226 +        {
 135.227 +                vidtime+=dispofftime;
 135.228 +
 135.229 +                cgastat|=1;
 135.230 +                linepos=1;
 135.231 +
 135.232 +                if (egadispon)
 135.233 +                {
 135.234 +                        if (firstline==2000) firstline=displine;
 135.235 +
 135.236 +                        if (scrblank)
 135.237 +                        {
 135.238 +                                for (x=0;x<ega_hdisp;x++)
 135.239 +                                {
 135.240 +                                        switch (seqregs[1]&9)
 135.241 +                                        {
 135.242 +                                                case 0:
 135.243 +                                                for (xx=0;xx<9;xx++) ((uint32_t *)buffer32->line[displine])[(x*9)+xx+32]=0;
 135.244 +                                                break;
 135.245 +                                                case 1:
 135.246 +                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[(x*8)+xx+32]=0;
 135.247 +                                                break;
 135.248 +                                                case 8:
 135.249 +                                                for (xx=0;xx<18;xx++) ((uint32_t *)buffer32->line[displine])[(x*18)+xx+32]=0;
 135.250 +                                                break;
 135.251 +                                                case 9:
 135.252 +                                                for (xx=0;xx<16;xx++) ((uint32_t *)buffer32->line[displine])[(x*16)+xx+32]=0;
 135.253 +                                                break;
 135.254 +                                        }
 135.255 +                                }
 135.256 +                        }
 135.257 +                        else if (!(gdcreg[6]&1))
 135.258 +                        {
 135.259 +                                if (fullchange)
 135.260 +                                {
 135.261 +                                        for (x=0;x<ega_hdisp;x++)
 135.262 +                                        {
 135.263 +                                                drawcursor=((ma==ca) && con && cursoron);
 135.264 +                                                chr=vram[(ma<<1)];
 135.265 +                                                attr=vram[(ma<<1)+4];
 135.266 +
 135.267 +                                                if (attr&8) charaddr=charsetb+(chr*128);
 135.268 +                                                else        charaddr=charseta+(chr*128);
 135.269 +
 135.270 +                                                if (drawcursor) { bg=pallook[egapal[attr&15]]; fg=pallook[egapal[attr>>4]]; }
 135.271 +                                                else
 135.272 +                                                {
 135.273 +                                                        fg=pallook[egapal[attr&15]];
 135.274 +                                                        bg=pallook[egapal[attr>>4]];
 135.275 +                                                        if (attr&0x80 && attrregs[0x10]&8)
 135.276 +                                                        {
 135.277 +                                                                bg=pallook[egapal[(attr>>4)&7]];
 135.278 +                                                                if (cgablink&16) fg=bg;
 135.279 +                                                        }
 135.280 +                                                }
 135.281 +
 135.282 +                                                dat=vram[charaddr+(sc<<2)];
 135.283 +                                                if (seqregs[1]&8)
 135.284 +                                                {
 135.285 +                                                        if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<4)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x<<4)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg; }
 135.286 +                                                        else
 135.287 +                                                        {
 135.288 +                                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*18)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg;
 135.289 +                                                                if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=bg;
 135.290 +                                                                else                  ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=(dat&1)?fg:bg;
 135.291 +                                                        }
 135.292 +                                                }
 135.293 +                                                else
 135.294 +                                                {
 135.295 +                                                        if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<3)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; }
 135.296 +                                                        else
 135.297 +                                                        {
 135.298 +                                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*9)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg;
 135.299 +                                                                if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=bg;
 135.300 +                                                                else                  ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=(dat&1)?fg:bg;
 135.301 +                                                        }
 135.302 +                                                }
 135.303 +                                                ma+=4; ma&=vrammask;
 135.304 +                                        }
 135.305 +                                }
 135.306 +                        }
 135.307 +                        else
 135.308 +                        {
 135.309 +                                switch (gdcreg[5]&0x20)
 135.310 +                                {
 135.311 +                                        case 0x00:
 135.312 +                                        if (seqregs[1]&8)
 135.313 +                                        {
 135.314 +                                                offset=((8-scrollcache)<<1)+16;
 135.315 +                                                for (x=0;x<=ega_hdisp;x++)
 135.316 +                                                {
 135.317 +                                                        if (sc&1 && !(crtc[0x17]&1))
 135.318 +                                                        {
 135.319 +                                                                edat[0] = vram[ma | 0x8000];
 135.320 +                                                                edat[1] = vram[ma | 0x8001];
 135.321 +                                                                edat[2] = vram[ma | 0x8002];
 135.322 +                                                                edat[3] = vram[ma | 0x8003];
 135.323 +                                                        }
 135.324 +                                                        else
 135.325 +                                                        {
 135.326 +                                                                edat[0] = vram[ma];
 135.327 +                                                                edat[1] = vram[ma | 0x1];
 135.328 +                                                                edat[2] = vram[ma | 0x2];
 135.329 +                                                                edat[3] = vram[ma | 0x3];
 135.330 +                                                        }
 135.331 +                                                        ma+=4; ma&=vrammask;
 135.332 +
 135.333 +                                                        dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
 135.334 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.335 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.336 +                                                        dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 135.337 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.338 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.339 +                                                        dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 135.340 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.341 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.342 +                                                        dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 135.343 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.344 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]=   ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.345 +                                                }
 135.346 +                                        }
 135.347 +                                        else
 135.348 +                                        {
 135.349 +                                                offset=(8-scrollcache)+24;
 135.350 +                                                for (x=0;x<=ega_hdisp;x++)
 135.351 +                                                {
 135.352 +                                                        if (sc&1 && !(crtc[0x17]&1))
 135.353 +                                                        {
 135.354 +                                                                edat[0] = vram[ma | 0x8000];
 135.355 +                                                                edat[1] = vram[ma | 0x8001];
 135.356 +                                                                edat[2] = vram[ma | 0x8002];
 135.357 +                                                                edat[3] = vram[ma | 0x8003];
 135.358 +                                                        }
 135.359 +                                                        else
 135.360 +                                                        {
 135.361 +                                                                edat[0] = vram[ma];
 135.362 +                                                                edat[1] = vram[ma | 0x1];
 135.363 +                                                                edat[2] = vram[ma | 0x2];
 135.364 +                                                                edat[3] = vram[ma | 0x3];
 135.365 +                                                        }
 135.366 +                                                        ma+=4; ma&=vrammask;
 135.367 +
 135.368 +                                                        dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
 135.369 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.370 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.371 +                                                        dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 135.372 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.373 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.374 +                                                        dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 135.375 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.376 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]=pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.377 +                                                        dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 135.378 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[egapal[(dat & 0xF) & attrregs[0x12]]];
 135.379 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+offset]=  pallook[egapal[(dat >> 4)  & attrregs[0x12]]];
 135.380 +                                                }
 135.381 +                                        }
 135.382 +                                        break;
 135.383 +                                        case 0x20:
 135.384 +                                        offset=((8-scrollcache)<<1)+16;
 135.385 +                                        for (x=0;x<=ega_hdisp;x++)
 135.386 +                                        {
 135.387 +                                                if (sc&1 && !(crtc[0x17]&1))
 135.388 +                                                {
 135.389 +                                                        edat[0]=vram[(ma<<1)+0x8000];
 135.390 +                                                        edat[1]=vram[(ma<<1)+0x8004];
 135.391 +                                                }
 135.392 +                                                else
 135.393 +                                                {
 135.394 +                                                        edat[0]=vram[(ma<<1)];
 135.395 +                                                        edat[1]=vram[(ma<<1)+4];
 135.396 +                                                }
 135.397 +                                                ma+=4; ma&=vrammask;
 135.398 +
 135.399 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[edat[1]&3]];
 135.400 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[(edat[1]>>2)&3]];
 135.401 +                                                dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 135.402 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[(edat[1]>>4)&3]];
 135.403 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[(edat[1]>>6)&3]];
 135.404 +                                                dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 135.405 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[(edat[0]>>0)&3]];
 135.406 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[(edat[0]>>2)&3]];
 135.407 +                                                dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 135.408 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[(edat[0]>>4)&3]];
 135.409 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]=   ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[(edat[0]>>6)&3]];
 135.410 +                                        }
 135.411 +                                        break;
 135.412 +                                }
 135.413 +                        }
 135.414 +                        if (lastline<displine) lastline=displine;
 135.415 +                }
 135.416 +
 135.417 +                displine++;
 135.418 +                if ((cgastat&8) && ((displine&15)==(crtc[0x11]&15)) && vslines)
 135.419 +                   cgastat&=~8;
 135.420 +                vslines++;
 135.421 +                if (displine>500) displine=0;
 135.422 +        }
 135.423 +        else
 135.424 +        {
 135.425 +                vidtime+=dispontime;
 135.426 +//                if (output) printf("Display on %f\n",vidtime);
 135.427 +                if (egadispon) cgastat&=~1;
 135.428 +                linepos=0;
 135.429 +                if (sc==(crtc[11]&31)) 
 135.430 +                   con=0; 
 135.431 +                if (egadispon)
 135.432 +                {
 135.433 +                        if (sc==(crtc[9]&31))
 135.434 +                        {
 135.435 +                                sc=0;
 135.436 +
 135.437 +                                maback+=(ega_rowoffset<<3);
 135.438 +                                maback&=vrammask;
 135.439 +                                ma=maback;
 135.440 +                        }
 135.441 +                        else
 135.442 +                        {
 135.443 +                                sc++;
 135.444 +                                sc&=31;
 135.445 +                                ma=maback;
 135.446 +                        }
 135.447 +                }
 135.448 +                vc++;
 135.449 +                vc&=1023;
 135.450 +//                printf("Line now %i %i ma %05X\n",vc,displine,ma);
 135.451 +                if (vc==ega_split)
 135.452 +                {
 135.453 +//                        printf("Split at line %i %i\n",displine,vc);
 135.454 +                        ma=maback=0;
 135.455 +                        if (attrregs[0x10]&0x20) scrollcache=0;
 135.456 +                }
 135.457 +                if (vc==ega_dispend)
 135.458 +                {
 135.459 +//                        printf("Display over at line %i %i\n",displine,vc);
 135.460 +                        egadispon=0;
 135.461 +                        if (crtc[10] & 0x20) cursoron=0;
 135.462 +                        else                 cursoron=cgablink&16;
 135.463 +                        if (!(gdcreg[6]&1) && !(cgablink&15)) fullchange=2;
 135.464 +                        cgablink++;
 135.465 +
 135.466 +                        for (x=0;x<2048;x++) if (changedvram[x]) changedvram[x]--;
 135.467 +//                        memset(changedvram,0,2048);
 135.468 +                        if (fullchange) fullchange--;
 135.469 +                }
 135.470 +                if (vc==ega_vsyncstart)
 135.471 +                {
 135.472 +                        egadispon=0;
 135.473 +//                        printf("Vsync on at line %i %i\n",displine,vc);
 135.474 +                        cgastat|=8;
 135.475 +                        if (seqregs[1]&8) x=ega_hdisp*((seqregs[1]&1)?8:9)*2;
 135.476 +                        else              x=ega_hdisp*((seqregs[1]&1)?8:9);
 135.477 +                        wx=x;
 135.478 +                        wy=lastline-firstline;
 135.479 +//                        pclog("Cursor %02X %02X\n",crtc[10],crtc[11]);
 135.480 +//                        pclog("Firstline %i Lastline %i wx %i %i\n",firstline,lastline,wx,oddeven);
 135.481 +//                        doblit();
 135.482 +                        svga_doblit(firstline, lastline + 1);
 135.483 +
 135.484 +                        video_res_x = wx;
 135.485 +                        video_res_y = wy + 1;
 135.486 +                        if (!(gdcreg[6]&1)) /*Text mode*/
 135.487 +                        {
 135.488 +                                video_res_x /= (seqregs[1] & 1) ? 8 : 9;
 135.489 +                                video_res_y /= (crtc[9] & 31) + 1;
 135.490 +                                video_bpp = 0;
 135.491 +                        }
 135.492 +                        else
 135.493 +                        {
 135.494 +                                if (crtc[9] & 0x80)
 135.495 +                                   video_res_y /= 2;
 135.496 +                                if (!(crtc[0x17] & 1))
 135.497 +                                   video_res_y *= 2;
 135.498 +                                video_res_y /= (crtc[9] & 31) + 1;                                   
 135.499 +                                if (seqregs[1] & 8)
 135.500 +                                   video_res_x /= 2;
 135.501 +                                video_bpp = (gdcreg[5] & 0x20) ? 2 : 4;
 135.502 +                        }
 135.503 +
 135.504 +//                        wakeupblit();
 135.505 +                        readflash=0;
 135.506 +                        //framecount++;
 135.507 +                        firstline=2000;
 135.508 +                        lastline=0;
 135.509 +
 135.510 +                        maback=ma=(crtc[0xC]<<8)|crtc[0xD];
 135.511 +                        ca=(crtc[0xE]<<8)|crtc[0xF];
 135.512 +                        ma<<=2;
 135.513 +                        maback<<=2;
 135.514 +                        ca<<=2;
 135.515 +                        changeframecount=2;
 135.516 +                        vslines=0;
 135.517 +                }
 135.518 +                if (vc==ega_vtotal)
 135.519 +                {
 135.520 +                        vc=0;
 135.521 +                        sc=0;
 135.522 +                        egadispon=1;
 135.523 +                        displine=0;
 135.524 +                        scrollcache=attrregs[0x13]&7;
 135.525 +                }
 135.526 +                if (sc == (crtc[10] & 31)) con=1;
 135.527 +        }
 135.528 +}
 135.529 +
 135.530 +
 135.531 +void ega_write(uint32_t addr, uint8_t val)
 135.532 +{
 135.533 +        int x,y;
 135.534 +        char s[2]={0,0};
 135.535 +        uint8_t vala,valb,valc,vald,wm=writemask;
 135.536 +
 135.537 +        egawrites++;
 135.538 +        cycles -= video_timing_b;
 135.539 +        cycles_lost += video_timing_b;
 135.540 +        
 135.541 +        if (addr>=0xB0000) addr &= 0x7fff;
 135.542 +        else               addr &= 0xffff;
 135.543 +
 135.544 +        if (!(gdcreg[6]&1)) fullchange=2;
 135.545 +        addr <<= 2;
 135.546 +
 135.547 +//        pclog("%i %08X %i %i %02X   %02X %02X %02X %02X\n",chain4,addr,writemode,writemask,gdcreg[8],vram[0],vram[1],vram[2],vram[3]);
 135.548 +        switch (writemode)
 135.549 +                {
 135.550 +                        case 1:
 135.551 +                        if (writemask&1) vram[addr]=la;
 135.552 +                        if (writemask&2) vram[addr|0x1]=lb;
 135.553 +                        if (writemask&4) vram[addr|0x2]=lc;
 135.554 +                        if (writemask&8) vram[addr|0x3]=ld;
 135.555 +                        break;
 135.556 +                        case 0:
 135.557 +                        if (gdcreg[3]&7) val=ega_rotate[gdcreg[3]&7][val];
 135.558 +                        if (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1])
 135.559 +                        {
 135.560 +//                                pclog("Easy write %05X %02X\n",addr,val);
 135.561 +                                if (writemask&1) vram[addr]=val;
 135.562 +                                if (writemask&2) vram[addr|0x1]=val;
 135.563 +                                if (writemask&4) vram[addr|0x2]=val;
 135.564 +                                if (writemask&8) vram[addr|0x3]=val;
 135.565 +                        }
 135.566 +                        else
 135.567 +                        {
 135.568 +                                if (gdcreg[1]&1) vala=(gdcreg[0]&1)?0xFF:0;
 135.569 +                                else             vala=val;
 135.570 +                                if (gdcreg[1]&2) valb=(gdcreg[0]&2)?0xFF:0;
 135.571 +                                else             valb=val;
 135.572 +                                if (gdcreg[1]&4) valc=(gdcreg[0]&4)?0xFF:0;
 135.573 +                                else             valc=val;
 135.574 +                                if (gdcreg[1]&8) vald=(gdcreg[0]&8)?0xFF:0;
 135.575 +                                else             vald=val;
 135.576 +//                                pclog("Write %02X %01X %02X %02X %02X %02X  %02X\n",gdcreg[3]&0x18,writemask,vala,valb,valc,vald,gdcreg[8]);
 135.577 +                                switch (gdcreg[3]&0x18)
 135.578 +                                {
 135.579 +                                        case 0: /*Set*/
 135.580 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
 135.581 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
 135.582 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
 135.583 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
 135.584 +                                        break;
 135.585 +                                        case 8: /*AND*/
 135.586 +                                        if (writemask&1) vram[addr]=(vala|~gdcreg[8])&la;
 135.587 +                                        if (writemask&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
 135.588 +                                        if (writemask&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
 135.589 +                                        if (writemask&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
 135.590 +                                        break;
 135.591 +                                        case 0x10: /*OR*/
 135.592 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])|la;
 135.593 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
 135.594 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
 135.595 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
 135.596 +                                        break;
 135.597 +                                        case 0x18: /*XOR*/
 135.598 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])^la;
 135.599 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
 135.600 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
 135.601 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
 135.602 +                                        break;
 135.603 +                                }
 135.604 +//                                pclog("- %02X %02X %02X %02X   %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
 135.605 +                        }
 135.606 +                        break;
 135.607 +                        case 2:
 135.608 +                        if (!(gdcreg[3]&0x18) && !gdcreg[1])
 135.609 +                        {
 135.610 +                                if (writemask&1) vram[addr]=(((val&1)?0xFF:0)&gdcreg[8])|(la&~gdcreg[8]);
 135.611 +                                if (writemask&2) vram[addr|0x1]=(((val&2)?0xFF:0)&gdcreg[8])|(lb&~gdcreg[8]);
 135.612 +                                if (writemask&4) vram[addr|0x2]=(((val&4)?0xFF:0)&gdcreg[8])|(lc&~gdcreg[8]);
 135.613 +                                if (writemask&8) vram[addr|0x3]=(((val&8)?0xFF:0)&gdcreg[8])|(ld&~gdcreg[8]);
 135.614 +                        }
 135.615 +                        else
 135.616 +                        {
 135.617 +                                vala=((val&1)?0xFF:0);
 135.618 +                                valb=((val&2)?0xFF:0);
 135.619 +                                valc=((val&4)?0xFF:0);
 135.620 +                                vald=((val&8)?0xFF:0);
 135.621 +                                switch (gdcreg[3]&0x18)
 135.622 +                                {
 135.623 +                                        case 0: /*Set*/
 135.624 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
 135.625 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
 135.626 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
 135.627 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
 135.628 +                                        break;
 135.629 +                                        case 8: /*AND*/
 135.630 +                                        if (writemask&1) vram[addr]=(vala|~gdcreg[8])&la;
 135.631 +                                        if (writemask&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
 135.632 +                                        if (writemask&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
 135.633 +                                        if (writemask&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
 135.634 +                                        break;
 135.635 +                                        case 0x10: /*OR*/
 135.636 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])|la;
 135.637 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
 135.638 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
 135.639 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
 135.640 +                                        break;
 135.641 +                                        case 0x18: /*XOR*/
 135.642 +                                        if (writemask&1) vram[addr]=(vala&gdcreg[8])^la;
 135.643 +                                        if (writemask&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
 135.644 +                                        if (writemask&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
 135.645 +                                        if (writemask&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
 135.646 +                                        break;
 135.647 +                                }
 135.648 +                        }
 135.649 +                        break;
 135.650 +                }
 135.651 +}
 135.652 +
 135.653 +uint8_t ega_read(uint32_t addr)
 135.654 +{
 135.655 +        uint8_t temp,temp2,temp3,temp4;
 135.656 +        uint32_t addr2;
 135.657 +        egareads++;
 135.658 +        cycles -= video_timing_b;
 135.659 +        cycles_lost += video_timing_b;
 135.660 +//        pclog("Readega %06X   ",addr);
 135.661 +        if (addr>=0xB0000) addr &= 0x7fff;
 135.662 +        else               addr &= 0xffff;
 135.663 +        addr<<=2;
 135.664 +        la=vram[addr];
 135.665 +        lb=vram[addr|0x1];
 135.666 +        lc=vram[addr|0x2];
 135.667 +        ld=vram[addr|0x3];
 135.668 +        if (readmode)
 135.669 +        {
 135.670 +                temp= (colournocare&1) ?0xFF:0;
 135.671 +                temp&=la;
 135.672 +                temp^=(colourcompare&1)?0xFF:0;
 135.673 +                temp2= (colournocare&2) ?0xFF:0;
 135.674 +                temp2&=lb;
 135.675 +                temp2^=(colourcompare&2)?0xFF:0;
 135.676 +                temp3= (colournocare&4) ?0xFF:0;
 135.677 +                temp3&=lc;
 135.678 +                temp3^=(colourcompare&4)?0xFF:0;
 135.679 +                temp4= (colournocare&8) ?0xFF:0;
 135.680 +                temp4&=ld;
 135.681 +                temp4^=(colourcompare&8)?0xFF:0;
 135.682 +                return ~(temp|temp2|temp3|temp4);
 135.683 +        }
 135.684 +        return vram[addr|readplane];
 135.685 +}
 135.686 +
 135.687 +int ega_init()
 135.688 +{
 135.689 +        int c, d, e;
 135.690 +        for (c = 0; c < 256; c++)
 135.691 +        {
 135.692 +                e = c;
 135.693 +                for (d = 0; d < 8; d++)
 135.694 +                {
 135.695 +                        ega_rotate[d][c] = e;
 135.696 +                        e = (e >> 1) | ((e & 1) ? 0x80 : 0);
 135.697 +                }
 135.698 +        }
 135.699 +        return 0;
 135.700 +}
 135.701 +
 135.702 +GFXCARD vid_ega =
 135.703 +{
 135.704 +        ega_init,
 135.705 +        /*IO at 3Cx/3Dx*/
 135.706 +        ega_out,
 135.707 +        ega_in,
 135.708 +        /*IO at 3Ax/3Bx*/
 135.709 +        video_out_null,
 135.710 +        video_in_null,
 135.711 +
 135.712 +        ega_poll,
 135.713 +        ega_recalctimings,
 135.714 +
 135.715 +        ega_write,
 135.716 +        video_write_null,
 135.717 +        video_write_null,
 135.718 +
 135.719 +        ega_read,
 135.720 +        video_read_null,
 135.721 +        video_read_null
 135.722 +};
 135.723 +
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/src/vid_ega.h	Sun Apr 21 14:54:35 2013 +0100
   136.3 @@ -0,0 +1,7 @@
   136.4 +int     ega_init();
   136.5 +void    ega_out(uint16_t addr, uint8_t val);
   136.6 +uint8_t ega_in(uint16_t addr);
   136.7 +void    ega_poll();
   136.8 +void    ega_recalctimings();
   136.9 +void    ega_write(uint32_t addr, uint8_t val);
  136.10 +uint8_t ega_read(uint32_t addr);
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/src/vid_et4000.c	Sun Apr 21 14:54:35 2013 +0100
   137.3 @@ -0,0 +1,141 @@
   137.4 +/*ET4000 emulation*/
   137.5 +#include "ibm.h"
   137.6 +#include "video.h"
   137.7 +#include "vid_svga.h"
   137.8 +#include "vid_unk_ramdac.h"
   137.9 +
  137.10 +int et4k_b8000;
  137.11 +
  137.12 +
  137.13 +void et4000_out(uint16_t addr, uint8_t val)
  137.14 +{
  137.15 +        uint8_t old;
  137.16 +        
  137.17 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  137.18 +
  137.19 +        pclog("ET4000 out %04X %02X\n", addr, val);
  137.20 +                
  137.21 +        switch (addr)
  137.22 +        {
  137.23 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  137.24 +                unk_ramdac_out(addr,val);
  137.25 +                return;
  137.26 +                
  137.27 +                case 0x3CD: /*Banking*/
  137.28 +                svgawbank=(val&0xF)*65536;
  137.29 +                svgarbank=((val>>4)&0xF)*65536;
  137.30 +                svgaseg=val;
  137.31 +                pclog("Banking write %08X %08X %02X\n", svgawbank, svgarbank, val);
  137.32 +                return;
  137.33 +                case 0x3CF:
  137.34 +                switch (gdcaddr&15)
  137.35 +                {
  137.36 +                        case 6:
  137.37 +                        et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
  137.38 +                        break;
  137.39 +                }
  137.40 +                break;
  137.41 +                case 0x3D4:
  137.42 +                crtcreg = val & 0x3f;
  137.43 +                return;
  137.44 +                case 0x3D5:
  137.45 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
  137.46 +                old=crtc[crtcreg];
  137.47 +                crtc[crtcreg]=val;
  137.48 +                et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
  137.49 +                if (old!=val)
  137.50 +                {
  137.51 +                        if (crtcreg<0xE || crtcreg>0x10)
  137.52 +                        {
  137.53 +                                fullchange=changeframecount;
  137.54 +                                svga_recalctimings();
  137.55 +                        }
  137.56 +                }
  137.57 +                break;
  137.58 +                case 0x3D8:
  137.59 +                if (val==0xA0) svgaon=1;
  137.60 +                if (val==0x29) svgaon=0;
  137.61 +                break;
  137.62 +        }
  137.63 +        svga_out(addr,val);
  137.64 +}
  137.65 +
  137.66 +uint8_t et4000_in(uint16_t addr)
  137.67 +{
  137.68 +        uint8_t temp;
  137.69 +                
  137.70 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  137.71 +        
  137.72 +        if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
  137.73 +        
  137.74 +        switch (addr)
  137.75 +        {
  137.76 +                case 0x3C5:
  137.77 +                if ((seqaddr&0xF)==7) return seqregs[seqaddr&0xF]|4;
  137.78 +                break;
  137.79 +
  137.80 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  137.81 +                return unk_ramdac_in(addr);
  137.82 +                
  137.83 +                case 0x3CD: /*Banking*/
  137.84 +                return svgaseg;
  137.85 +                case 0x3D4:
  137.86 +                return crtcreg;
  137.87 +                case 0x3D5:
  137.88 +                return crtc[crtcreg];
  137.89 +        }
  137.90 +        return svga_in(addr);
  137.91 +}
  137.92 +
  137.93 +void et4000_recalctimings()
  137.94 +{
  137.95 +        svga_ma|=(crtc[0x33]&3)<<16;
  137.96 +        if (crtc[0x35]&2)    svga_vtotal+=0x400;
  137.97 +        if (crtc[0x35]&4)    svga_dispend+=0x400;
  137.98 +        if (crtc[0x35]&8)    svga_vsyncstart+=0x400;
  137.99 +        if (crtc[0x35]&0x10) svga_split+=0x400;
 137.100 +        if (!svga_rowoffset) svga_rowoffset=0x100;
 137.101 +//        if (crtc[0x3F]&0x80) svga_rowoffset+=0x100;
 137.102 +        if (crtc[0x3F]&1)    svga_htotal+=256;
 137.103 +        if (attrregs[0x16]&0x20) svga_hdisp<<=1;
 137.104 +//        pclog("Rowoffset %i\n",svga_rowoffset);
 137.105 +
 137.106 +        switch (((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4))
 137.107 +        {
 137.108 +                case 0: case 1: break;
 137.109 +                case 3: svga_clock = cpuclock/40000000.0; break;
 137.110 +                case 5: svga_clock = cpuclock/65000000.0; break;
 137.111 +                default: svga_clock = cpuclock/36000000.0; break;
 137.112 +        }
 137.113 +
 137.114 +}
 137.115 +
 137.116 +int et4000_init()
 137.117 +{
 137.118 +        svga_recalctimings_ex = et4000_recalctimings;
 137.119 +        svga_vram_limit = 1 << 20; /*1mb*/
 137.120 +        vrammask = 0xfffff;
 137.121 +        return svga_init();
 137.122 +}
 137.123 +
 137.124 +GFXCARD vid_et4000 =
 137.125 +{
 137.126 +        et4000_init,
 137.127 +        /*IO at 3Cx/3Dx*/
 137.128 +        et4000_out,
 137.129 +        et4000_in,
 137.130 +        /*IO at 3Ax/3Bx*/
 137.131 +        video_out_null,
 137.132 +        video_in_null,
 137.133 +
 137.134 +        svga_poll,
 137.135 +        svga_recalctimings,
 137.136 +
 137.137 +        svga_write,
 137.138 +        video_write_null,
 137.139 +        video_write_null,
 137.140 +
 137.141 +        svga_read,
 137.142 +        video_read_null,
 137.143 +        video_read_null
 137.144 +};
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/src/vid_et4000w32.c	Sun Apr 21 14:54:35 2013 +0100
   138.3 @@ -0,0 +1,936 @@
   138.4 +/*ET4000/W32p emulation (Diamond Stealth 32)*/
   138.5 +/*Known bugs :
   138.6 +
   138.7 +  - Accelerator doesn't work in planar modes
   138.8 +*/
   138.9 +
  138.10 +#include "ibm.h"
  138.11 +#include "video.h"
  138.12 +#include "vid_svga.h"
  138.13 +#include "vid_icd2061.h"
  138.14 +#include "vid_stg_ramdac.h"
  138.15 +#include "mem.h"
  138.16 +
  138.17 +int et4k_b8000;
  138.18 +
  138.19 +void et4000w32p_recalcmapping();
  138.20 +
  138.21 +uint8_t et4000w32p_mmu_read(uint32_t addr);
  138.22 +void et4000w32p_mmu_write(uint32_t addr, uint8_t val);
  138.23 +
  138.24 +static int et4000w32p_index;
  138.25 +static uint8_t et4000w32p_regs[256];
  138.26 +static uint32_t et4000w32p_linearbase, et4000w32p_linearbase_old;
  138.27 +
  138.28 +void et4000w32p_out(uint16_t addr, uint8_t val)
  138.29 +{
  138.30 +        uint8_t old;
  138.31 +
  138.32 +//        if (!(addr==0x3D4 && (val&~1)==0xE) && !(addr==0x3D5 && (crtcreg&~1)==0xE)) pclog("ET4000W32p out %04X %02X  %04X:%04X  ",addr,val,CS,pc);
  138.33 +        
  138.34 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  138.35 +        
  138.36 +//        if (!(addr==0x3D4 && (val&~1)==0xE) && !(addr==0x3D5 && (crtcreg&~1)==0xE)) pclog("%04X\n",addr);
  138.37 +        
  138.38 +        switch (addr)
  138.39 +        {
  138.40 +                case 0x3c2:
  138.41 +                icd2061_write((val >> 2) & 3);
  138.42 +                break;
  138.43 +                
  138.44 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  138.45 +                stg_ramdac_out(addr,val);
  138.46 +                return;
  138.47 +                
  138.48 +                case 0x3CB: /*Banking extension*/
  138.49 +                svgawbank=(svgawbank&0xFFFFF)|((val&1)<<20);
  138.50 +                svgarbank=(svgarbank&0xFFFFF)|((val&0x10)<<16);
  138.51 +                svgaseg2=val;
  138.52 +                return;
  138.53 +                case 0x3CD: /*Banking*/
  138.54 +                svgawbank=(svgawbank&0x100000)|((val&0xF)*65536);
  138.55 +                svgarbank=(svgarbank&0x100000)|(((val>>4)&0xF)*65536);
  138.56 +                svgaseg=val;
  138.57 +                return;
  138.58 +                case 0x3CF:
  138.59 +                switch (gdcaddr&15)
  138.60 +                {
  138.61 +                        case 6:
  138.62 +                        gdcreg[gdcaddr&15]=val;
  138.63 +                        //et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
  138.64 +                        et4000w32p_recalcmapping();
  138.65 +                        return;
  138.66 +                }
  138.67 +                break;
  138.68 +                case 0x3D4:
  138.69 +                crtcreg=val&63;
  138.70 +                return;
  138.71 +                case 0x3D5:
  138.72 +//                pclog("Write CRTC R%02X %02X\n", crtcreg, val);
  138.73 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
  138.74 +                old=crtc[crtcreg];
  138.75 +                crtc[crtcreg]=val;
  138.76 +                et4k_b8000=((crtc[0x36]&0x38)==0x28) && ((gdcreg[6]&0xC)==4);
  138.77 +//                if (crtcreg!=0xE && crtcreg!=0xF) pclog("CRTC R%02X = %02X\n",crtcreg,val);
  138.78 +                if (old!=val)
  138.79 +                {
  138.80 +                        if (crtcreg<0xE || crtcreg>0x10)
  138.81 +                        {
  138.82 +                                fullchange=changeframecount;
  138.83 +                                svga_recalctimings();
  138.84 +                        }
  138.85 +                }
  138.86 +                if (crtcreg == 0x30)
  138.87 +                {
  138.88 +                        et4000w32p_linearbase = val * 0x400000;
  138.89 +//                        pclog("Linear base now at %08X %02X\n", et4000w32p_linearbase, val);
  138.90 +                        et4000w32p_recalcmapping();
  138.91 +                }
  138.92 +                if (crtcreg == 0x36) et4000w32p_recalcmapping();
  138.93 +                break;
  138.94 +                case 0x3D8:
  138.95 +                if (val==0xA0) svgaon=1;
  138.96 +                if (val==0x29) svgaon=0;
  138.97 +                break;
  138.98 +
  138.99 +                case 0x210A: case 0x211A: case 0x212A: case 0x213A:
 138.100 +                case 0x214A: case 0x215A: case 0x216A: case 0x217A:
 138.101 +                et4000w32p_index=val;
 138.102 +                return;
 138.103 +                case 0x210B: case 0x211B: case 0x212B: case 0x213B:
 138.104 +                case 0x214B: case 0x215B: case 0x216B: case 0x217B:
 138.105 +                et4000w32p_regs[et4000w32p_index] = val;
 138.106 +                svga_hwcursor.x     = et4000w32p_regs[0xE0] | ((et4000w32p_regs[0xE1] & 7) << 8);
 138.107 +                svga_hwcursor.y     = et4000w32p_regs[0xE4] | ((et4000w32p_regs[0xE5] & 7) << 8);
 138.108 +                svga_hwcursor.addr  = (et4000w32p_regs[0xE8] | (et4000w32p_regs[0xE9] << 8) | ((et4000w32p_regs[0xEA] & 7) << 16)) << 2;
 138.109 +                svga_hwcursor.addr += (et4000w32p_regs[0xE6] & 63) * 16;
 138.110 +                svga_hwcursor.ena   = et4000w32p_regs[0xF7] & 0x80;
 138.111 +                svga_hwcursor.xoff  = et4000w32p_regs[0xE2] & 63;
 138.112 +                svga_hwcursor.yoff  = et4000w32p_regs[0xE6] & 63;
 138.113 +//                pclog("HWCURSOR X %i Y %i\n",svga_hwcursor_x,svga_hwcursor_y);
 138.114 +                return;
 138.115 +
 138.116 +        }
 138.117 +        svga_out(addr,val);
 138.118 +}
 138.119 +
 138.120 +uint8_t et4000w32p_in(uint16_t addr)
 138.121 +{
 138.122 +        uint8_t temp;
 138.123 +//        if (addr==0x3DA) pclog("In 3DA %04X(%06X):%04X\n",CS,cs,pc);
 138.124 +        
 138.125 +//        pclog("ET4000W32p in  %04X  %04X:%04X  ",addr,CS,pc);
 138.126 +
 138.127 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
 138.128 +        
 138.129 +//        pclog("%04X\n",addr);
 138.130 +        
 138.131 +        switch (addr)
 138.132 +        {
 138.133 +                case 0x3C5:
 138.134 +                if ((seqaddr&0xF)==7) return seqregs[seqaddr&0xF]|4;
 138.135 +                break;
 138.136 +
 138.137 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
 138.138 +                return stg_ramdac_in(addr);
 138.139 +
 138.140 +                case 0x3CB:
 138.141 +                return svgaseg2;
 138.142 +                case 0x3CD:
 138.143 +                return svgaseg;
 138.144 +                case 0x3D4:
 138.145 +                return crtcreg;
 138.146 +                case 0x3D5:
 138.147 +//                pclog("Read CRTC R%02X %02X\n", crtcreg, crtc[crtcreg]);
 138.148 +                return crtc[crtcreg];
 138.149 +                
 138.150 +                case 0x3DA:
 138.151 +                attrff=0;
 138.152 +                cgastat^=0x30;
 138.153 +                temp = cgastat & 0x39;
 138.154 +                if (svga_hdisp_on) temp |= 2;
 138.155 +                if (!(cgastat & 8)) temp |= 0x80;
 138.156 +//                pclog("3DA in %02X\n",temp);
 138.157 +                return temp;
 138.158 +
 138.159 +                case 0x210A: case 0x211A: case 0x212A: case 0x213A:
 138.160 +                case 0x214A: case 0x215A: case 0x216A: case 0x217A:
 138.161 +                return et4000w32p_index;
 138.162 +                case 0x210B: case 0x211B: case 0x212B: case 0x213B:
 138.163 +                case 0x214B: case 0x215B: case 0x216B: case 0x217B:
 138.164 +                if (et4000w32p_index==0xEC) return (et4000w32p_regs[0xEC]&0xF)|0x60; /*ET4000/W32p rev D*/
 138.165 +                if (et4000w32p_index == 0xEF) 
 138.166 +                {
 138.167 +                        if (PCI) return et4000w32p_regs[0xEF] | 0xe0;       /*PCI*/
 138.168 +                        else     return et4000w32p_regs[0xEF] | 0x60;       /*VESA local bus*/
 138.169 +                }
 138.170 +                return et4000w32p_regs[et4000w32p_index];
 138.171 +        }
 138.172 +        return svga_in(addr);
 138.173 +}
 138.174 +
 138.175 +void et4000w32p_recalctimings()
 138.176 +{
 138.177 +        double clk;
 138.178 +//        pclog("Recalc %08X  ",svga_ma);
 138.179 +        svga_ma|=(crtc[0x33]&0x7)<<16;
 138.180 +        pclog("SVGA_MA %08X %i\n", svga_ma, (svga_miscout >> 2) & 3);
 138.181 +        if (crtc[0x35]&2)    svga_vtotal+=0x400;
 138.182 +        if (crtc[0x35]&4)    svga_dispend+=0x400;
 138.183 +        if (crtc[0x35]&8)    svga_vsyncstart+=0x400;
 138.184 +        if (crtc[0x35]&0x10) svga_split+=0x400;
 138.185 +        if (crtc[0x3F]&0x80) svga_rowoffset+=0x100;
 138.186 +        if (crtc[0x3F]&1)    svga_htotal+=256;
 138.187 +        if (attrregs[0x16]&0x20) svga_hdisp<<=1;
 138.188 +        
 138.189 +        switch ((svga_miscout >> 2) & 3)
 138.190 +        {
 138.191 +                case 0: case 1: break;
 138.192 +                case 2: case 3: svga_clock = cpuclock/icd2061_getfreq(2); break;
 138.193 +/*                default: 
 138.194 +                        pclog("Unknown clock %i\n", ((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4) | ((crtc[0x31] & 0xc0) >> 3));
 138.195 +                        svga_clock = cpuclock/36000000.0; break;*/
 138.196 +        }
 138.197 +        
 138.198 +//        pclog("Recalctimings - %02X %02X %02X\n", crtc[6], crtc[7], crtc[0x35]);
 138.199 +}
 138.200 +
 138.201 +int et4000w32p_getclock()
 138.202 +{
 138.203 +        return ((svga_miscout >> 2) & 3) | ((crtc[0x34] << 1) & 4) | ((crtc[0x31] & 0xc0) >> 3);
 138.204 +}
 138.205 +
 138.206 +
 138.207 +void et4000w32p_recalcmapping()
 138.208 +{
 138.209 +        int map;
 138.210 +        
 138.211 +        mem_removehandler(et4000w32p_linearbase_old, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear);
 138.212 +        mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.213 +        mem_removehandler(0xb0000, 0x10000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL);    
 138.214 +        if (crtc[0x36] & 0x10) /*Linear frame buffer*/
 138.215 +        {
 138.216 +                mem_sethandler(et4000w32p_linearbase, 0x200000, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear);
 138.217 +        }
 138.218 +        else
 138.219 +        {
 138.220 +                map = (gdcreg[6] & 0xC) >> 2;
 138.221 +                if (crtc[0x36] & 0x20) map |= 4;
 138.222 +                if (crtc[0x36] & 0x08) map |= 8;
 138.223 +                switch (map)
 138.224 +                {
 138.225 +                        case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/
 138.226 +                        mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.227 +                        break;
 138.228 +                        case 0x1: /*64k at A0000*/
 138.229 +                        mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.230 +                        break;
 138.231 +                        case 0x2: /*32k at B0000*/
 138.232 +                        mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.233 +                        break;
 138.234 +                        case 0x3: /*32k at B8000*/
 138.235 +                        mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.236 +                        break;
 138.237 +                        case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/
 138.238 +                        mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.239 +                        mem_sethandler(0xb8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL);                        
 138.240 +                        break;
 138.241 +                        case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/
 138.242 +                        mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL);                        
 138.243 +                        mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.244 +                        break;
 138.245 +                        case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/
 138.246 +                        mem_sethandler(0xa8000, 0x08000, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL);    
 138.247 +                        mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 138.248 +                        break;
 138.249 +                }
 138.250 +//                pclog("ET4K map %02X\n", map);
 138.251 +        }
 138.252 +        et4000w32p_linearbase_old = et4000w32p_linearbase;
 138.253 +}
 138.254 +
 138.255 +/*Accelerator*/
 138.256 +struct
 138.257 +{
 138.258 +        struct
 138.259 +        {
 138.260 +                uint32_t pattern_addr,source_addr,dest_addr,mix_addr;
 138.261 +                uint16_t pattern_off,source_off,dest_off,mix_off;
 138.262 +                uint8_t pixel_depth,xy_dir;
 138.263 +                uint8_t pattern_wrap,source_wrap;
 138.264 +                uint16_t count_x,count_y;
 138.265 +                uint8_t ctrl_routing,ctrl_reload;
 138.266 +                uint8_t rop_fg,rop_bg;
 138.267 +                uint16_t pos_x,pos_y;
 138.268 +                uint16_t error;
 138.269 +                uint16_t dmin,dmaj;
 138.270 +        } queued,internal;
 138.271 +        uint32_t pattern_addr,source_addr,dest_addr,mix_addr;
 138.272 +        uint32_t pattern_back,source_back,dest_back,mix_back;
 138.273 +        int pattern_x,source_x;
 138.274 +        int pattern_x_back,source_x_back;
 138.275 +        int pattern_y,source_y;
 138.276 +        uint8_t status;
 138.277 +        uint64_t cpu_dat;
 138.278 +        int cpu_dat_pos;
 138.279 +        int pix_pos;
 138.280 +} acl;
 138.281 +
 138.282 +#define ACL_WRST 1
 138.283 +#define ACL_RDST 2
 138.284 +#define ACL_XYST 4
 138.285 +#define ACL_SSO  8
 138.286 +
 138.287 +struct
 138.288 +{
 138.289 +        uint32_t base[3];
 138.290 +        uint8_t ctrl;
 138.291 +} mmu;
 138.292 +
 138.293 +void et4000w32_reset()
 138.294 +{
 138.295 +        acl.status=0;
 138.296 +}
 138.297 +
 138.298 +void et4000w32_blit_start();
 138.299 +void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input);
 138.300 +
 138.301 +void et4000w32p_mmu_write(uint32_t addr, uint8_t val)
 138.302 +{
 138.303 +        int bank;
 138.304 +//        pclog("ET4K write %08X %02X %02X %04X(%08X):%08X\n",addr,val,acl.status,acl.internal.ctrl_routing,CS,cs,pc);
 138.305 +        switch (addr&0x6000)
 138.306 +        {
 138.307 +                case 0x0000: /*MMU 0*/
 138.308 +                case 0x2000: /*MMU 1*/
 138.309 +                case 0x4000: /*MMU 2*/
 138.310 +                bank=(addr>>13)&3;
 138.311 +                if (mmu.ctrl&(1<<bank))
 138.312 +                {
 138.313 +                        if (!(acl.status&ACL_XYST)) return;
 138.314 +                        if (acl.internal.ctrl_routing&3)
 138.315 +                        {
 138.316 +                                if ((acl.internal.ctrl_routing&3)==2)
 138.317 +                                {
 138.318 +                                        if (acl.mix_addr&7)
 138.319 +                                           et4000w32_blit(8-(acl.mix_addr&7), val>>(acl.mix_addr&7), 0, 1);
 138.320 +                                        else
 138.321 +                                           et4000w32_blit(8, val, 0, 1);
 138.322 +                                }
 138.323 +                                else if ((acl.internal.ctrl_routing&3)==1)
 138.324 +                                   et4000w32_blit(1, ~0, val, 2);
 138.325 +//                                else
 138.326 +//                                   pclog("Bad ET4K routing %i\n",acl.internal.ctrl_routing&7);
 138.327 +                        }
 138.328 +                }
 138.329 +                else
 138.330 +                {
 138.331 +                        vram[(addr&0x1FFF)+mmu.base[bank]]=val;
 138.332 +                        changedvram[((addr&0x1FFF)+mmu.base[bank])>>10]=changeframecount;
 138.333 +                }
 138.334 +                break;
 138.335 +                case 0x6000:
 138.336 +                switch (addr&0x7FFF)
 138.337 +                {
 138.338 +                        case 0x7F00: mmu.base[0]=(mmu.base[0]&0xFFFFFF00)|val;       break;
 138.339 +                        case 0x7F01: mmu.base[0]=(mmu.base[0]&0xFFFF00FF)|(val<<8);  break;
 138.340 +                        case 0x7F02: mmu.base[0]=(mmu.base[0]&0xFF00FFFF)|(val<<16); break;
 138.341 +                        case 0x7F03: mmu.base[0]=(mmu.base[0]&0x00FFFFFF)|(val<<24); break;
 138.342 +                        case 0x7F04: mmu.base[1]=(mmu.base[1]&0xFFFFFF00)|val;       break;
 138.343 +                        case 0x7F05: mmu.base[1]=(mmu.base[1]&0xFFFF00FF)|(val<<8);  break;
 138.344 +                        case 0x7F06: mmu.base[1]=(mmu.base[1]&0xFF00FFFF)|(val<<16); break;
 138.345 +                        case 0x7F07: mmu.base[1]=(mmu.base[1]&0x00FFFFFF)|(val<<24); break;
 138.346 +                        case 0x7F08: mmu.base[2]=(mmu.base[2]&0xFFFFFF00)|val;       break;
 138.347 +                        case 0x7F09: mmu.base[2]=(mmu.base[2]&0xFFFF00FF)|(val<<8);  break;
 138.348 +                        case 0x7F0A: mmu.base[2]=(mmu.base[2]&0xFF00FFFF)|(val<<16); break;
 138.349 +                        case 0x7F0B: mmu.base[2]=(mmu.base[2]&0x00FFFFFF)|(val<<24); break;
 138.350 +                        case 0x7F13: mmu.ctrl=val; break;
 138.351 +
 138.352 +                        case 0x7F80: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFFFF00)|val;       break;
 138.353 +                        case 0x7F81: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFF00FF)|(val<<8);  break;
 138.354 +                        case 0x7F82: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFF00FFFF)|(val<<16); break;
 138.355 +                        case 0x7F83: acl.queued.pattern_addr=(acl.queued.pattern_addr&0x00FFFFFF)|(val<<24); break;
 138.356 +                        case 0x7F84: acl.queued.source_addr =(acl.queued.source_addr &0xFFFFFF00)|val;       break;
 138.357 +                        case 0x7F85: acl.queued.source_addr =(acl.queued.source_addr &0xFFFF00FF)|(val<<8);  break;
 138.358 +                        case 0x7F86: acl.queued.source_addr =(acl.queued.source_addr &0xFF00FFFF)|(val<<16); break;
 138.359 +                        case 0x7F87: acl.queued.source_addr =(acl.queued.source_addr &0x00FFFFFF)|(val<<24); break;
 138.360 +                        case 0x7F88: acl.queued.pattern_off=(acl.queued.pattern_off&0xFF00)|val;      break;
 138.361 +                        case 0x7F89: acl.queued.pattern_off=(acl.queued.pattern_off&0x00FF)|(val<<8); break;
 138.362 +                        case 0x7F8A: acl.queued.source_off =(acl.queued.source_off &0xFF00)|val;      break;
 138.363 +                        case 0x7F8B: acl.queued.source_off =(acl.queued.source_off &0x00FF)|(val<<8); break;
 138.364 +                        case 0x7F8C: acl.queued.dest_off   =(acl.queued.dest_off   &0xFF00)|val;      break;
 138.365 +                        case 0x7F8D: acl.queued.dest_off   =(acl.queued.dest_off   &0x00FF)|(val<<8); break;
 138.366 +                        case 0x7F8E: acl.queued.pixel_depth=val; break;
 138.367 +                        case 0x7F8F: acl.queued.xy_dir=val; break;
 138.368 +                        case 0x7F90: acl.queued.pattern_wrap=val; break;
 138.369 +                        case 0x7F92: acl.queued.source_wrap=val; break;
 138.370 +                        case 0x7F98: acl.queued.count_x    =(acl.queued.count_x    &0xFF00)|val;      break;
 138.371 +                        case 0x7F99: acl.queued.count_x    =(acl.queued.count_x    &0x00FF)|(val<<8); break;
 138.372 +                        case 0x7F9A: acl.queued.count_y    =(acl.queued.count_y    &0xFF00)|val;      break;
 138.373 +                        case 0x7F9B: acl.queued.count_y    =(acl.queued.count_y    &0x00FF)|(val<<8); break;
 138.374 +                        case 0x7F9C: acl.queued.ctrl_routing=val; break;
 138.375 +                        case 0x7F9D: acl.queued.ctrl_reload =val; break;
 138.376 +                        case 0x7F9E: acl.queued.rop_bg      =val; break;
 138.377 +                        case 0x7F9F: acl.queued.rop_fg      =val; break;
 138.378 +                        case 0x7FA0: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFFFFFF00)|val;       break;
 138.379 +                        case 0x7FA1: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFFFF00FF)|(val<<8);  break;
 138.380 +                        case 0x7FA2: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFF00FFFF)|(val<<16); break;
 138.381 +                        case 0x7FA3: acl.queued.dest_addr   =(acl.queued.dest_addr   &0x00FFFFFF)|(val<<24);
 138.382 +                        acl.internal=acl.queued;
 138.383 +                        et4000w32_blit_start();
 138.384 +                        if (!(acl.queued.ctrl_routing&0x43))
 138.385 +                        {
 138.386 +                                et4000w32_blit(0xFFFFFF, ~0, 0, 0);
 138.387 +                        }
 138.388 +                        if ((acl.queued.ctrl_routing&0x40) && !(acl.internal.ctrl_routing&3))
 138.389 +                           et4000w32_blit(4, ~0, 0, 0);
 138.390 +                        break;
 138.391 +                        case 0x7FA4: acl.queued.mix_addr=(acl.queued.mix_addr&0xFFFFFF00)|val;       break;
 138.392 +                        case 0x7FA5: acl.queued.mix_addr=(acl.queued.mix_addr&0xFFFF00FF)|(val<<8);  break;
 138.393 +                        case 0x7FA6: acl.queued.mix_addr=(acl.queued.mix_addr&0xFF00FFFF)|(val<<16); break;
 138.394 +                        case 0x7FA7: acl.queued.mix_addr=(acl.queued.mix_addr&0x00FFFFFF)|(val<<24); break;
 138.395 +                        case 0x7FA8: acl.queued.mix_off    =(acl.queued.mix_off    &0xFF00)|val;      break;
 138.396 +                        case 0x7FA9: acl.queued.mix_off    =(acl.queued.mix_off    &0x00FF)|(val<<8); break;
 138.397 +                        case 0x7FAA: acl.queued.error      =(acl.queued.error      &0xFF00)|val;      break;
 138.398 +                        case 0x7FAB: acl.queued.error      =(acl.queued.error      &0x00FF)|(val<<8); break;
 138.399 +                        case 0x7FAC: acl.queued.dmin       =(acl.queued.dmin       &0xFF00)|val;      break;
 138.400 +                        case 0x7FAD: acl.queued.dmin       =(acl.queued.dmin       &0x00FF)|(val<<8); break;
 138.401 +                        case 0x7FAE: acl.queued.dmaj       =(acl.queued.dmaj       &0xFF00)|val;      break;
 138.402 +                        case 0x7FAF: acl.queued.dmaj       =(acl.queued.dmaj       &0x00FF)|(val<<8); break;
 138.403 +                }
 138.404 +                break;
 138.405 +        }
 138.406 +}
 138.407 +
 138.408 +uint8_t et4000w32p_mmu_read(uint32_t addr)
 138.409 +{
 138.410 +        int bank;
 138.411 +        uint8_t temp;
 138.412 +//        pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc);
 138.413 +        switch (addr&0x6000)
 138.414 +        {
 138.415 +                case 0x0000: /*MMU 0*/
 138.416 +                case 0x2000: /*MMU 1*/
 138.417 +                case 0x4000: /*MMU 2*/
 138.418 +                bank=(addr>>13)&3;
 138.419 +                if (mmu.ctrl&(1<<bank))
 138.420 +                {
 138.421 +                        temp=0xFF;
 138.422 +                        if (acl.cpu_dat_pos)
 138.423 +                        {
 138.424 +                                acl.cpu_dat_pos--;
 138.425 +                                temp=acl.cpu_dat&0xFF;
 138.426 +                                acl.cpu_dat>>=8;
 138.427 +                        }
 138.428 +                        if ((acl.queued.ctrl_routing&0x40) && !acl.cpu_dat_pos && !(acl.internal.ctrl_routing&3))
 138.429 +                           et4000w32_blit(4, ~0, 0, 0);
 138.430 +                        /*???*/
 138.431 +                        return temp;
 138.432 +                }
 138.433 +                return vram[(addr&0x1FFF)+mmu.base[bank]];
 138.434 +                case 0x6000:
 138.435 +                switch (addr&0x7FFF)
 138.436 +                {
 138.437 +                        case 0x7F00: return mmu.base[0];
 138.438 +                        case 0x7F01: return mmu.base[0]>>8;
 138.439 +                        case 0x7F02: return mmu.base[0]>>16;
 138.440 +                        case 0x7F03: return mmu.base[0]>>24;
 138.441 +                        case 0x7F04: return mmu.base[1];
 138.442 +                        case 0x7F05: return mmu.base[1]>>8;
 138.443 +                        case 0x7F06: return mmu.base[1]>>16;
 138.444 +                        case 0x7F07: return mmu.base[1]>>24;
 138.445 +                        case 0x7F08: return mmu.base[2];
 138.446 +                        case 0x7F09: return mmu.base[2]>>8;
 138.447 +                        case 0x7F0A: return mmu.base[2]>>16;
 138.448 +                        case 0x7F0B: return mmu.base[2]>>24;
 138.449 +                        case 0x7F13: return mmu.ctrl;
 138.450 +
 138.451 +                        case 0x7F36:
 138.452 +//                                pclog("Read ACL status %02X\n",acl.status);
 138.453 +//                        if (acl.internal.pos_x!=acl.internal.count_x || acl.internal.pos_y!=acl.internal.count_y) return acl.status | ACL_XYST;
 138.454 +                        return acl.status;
 138.455 +                        case 0x7F80: return acl.internal.pattern_addr;
 138.456 +                        case 0x7F81: return acl.internal.pattern_addr>>8;
 138.457 +                        case 0x7F82: return acl.internal.pattern_addr>>16;
 138.458 +                        case 0x7F83: return acl.internal.pattern_addr>>24;
 138.459 +                        case 0x7F84: return acl.internal.source_addr;
 138.460 +                        case 0x7F85: return acl.internal.source_addr>>8;
 138.461 +                        case 0x7F86: return acl.internal.source_addr>>16;
 138.462 +                        case 0x7F87: return acl.internal.source_addr>>24;
 138.463 +                        case 0x7F88: return acl.internal.pattern_off;
 138.464 +                        case 0x7F89: return acl.internal.pattern_off>>8;
 138.465 +                        case 0x7F8A: return acl.internal.source_off;
 138.466 +                        case 0x7F8B: return acl.internal.source_off>>8;
 138.467 +                        case 0x7F8C: return acl.internal.dest_off;
 138.468 +                        case 0x7F8D: return acl.internal.dest_off>>8;
 138.469 +                        case 0x7F8E: return acl.internal.pixel_depth;
 138.470 +                        case 0x7F8F: return acl.internal.xy_dir;
 138.471 +                        case 0x7F90: return acl.internal.pattern_wrap;
 138.472 +                        case 0x7F92: return acl.internal.source_wrap;
 138.473 +                        case 0x7F98: return acl.internal.count_x;
 138.474 +                        case 0x7F99: return acl.internal.count_x>>8;
 138.475 +                        case 0x7F9A: return acl.internal.count_y;
 138.476 +                        case 0x7F9B: return acl.internal.count_y>>8;
 138.477 +                        case 0x7F9C: return acl.internal.ctrl_routing;
 138.478 +                        case 0x7F9D: return acl.internal.ctrl_reload;
 138.479 +                        case 0x7F9E: return acl.internal.rop_bg;
 138.480 +                        case 0x7F9F: return acl.internal.rop_fg;
 138.481 +                        case 0x7FA0: return acl.internal.dest_addr;
 138.482 +                        case 0x7FA1: return acl.internal.dest_addr>>8;
 138.483 +                        case 0x7FA2: return acl.internal.dest_addr>>16;
 138.484 +                        case 0x7FA3: return acl.internal.dest_addr>>24;
 138.485 +                }
 138.486 +                return 0xFF;
 138.487 +        }
 138.488 +}
 138.489 +
 138.490 +int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000};
 138.491 +int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF};
 138.492 +int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
 138.493 +
 138.494 +int bltout=0;
 138.495 +void et4000w32_blit_start()
 138.496 +{
 138.497 +//        if (acl.queued.xy_dir&0x80)
 138.498 +//           pclog("Blit - %02X %08X (%i,%i) %08X (%i,%i) %08X (%i,%i) %i  %i %i  %02X %02X  %02X\n",acl.queued.xy_dir,acl.internal.pattern_addr,(acl.internal.pattern_addr/3)%640,(acl.internal.pattern_addr/3)/640,acl.internal.source_addr,(acl.internal.source_addr/3)%640,(acl.internal.source_addr/3)/640,acl.internal.dest_addr,(acl.internal.dest_addr/3)%640,(acl.internal.dest_addr/3)/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing);
 138.499 +//           bltout=1;
 138.500 +//        bltout=(acl.internal.count_x==1541);
 138.501 +        if (!(acl.queued.xy_dir&0x20))
 138.502 +           acl.internal.error = acl.internal.dmaj/2;
 138.503 +        acl.pattern_addr=acl.internal.pattern_addr;
 138.504 +        acl.source_addr =acl.internal.source_addr;
 138.505 +        acl.mix_addr    =acl.internal.mix_addr;
 138.506 +        acl.mix_back    =acl.mix_addr;
 138.507 +        acl.dest_addr   =acl.internal.dest_addr;
 138.508 +        acl.dest_back   =acl.dest_addr;
 138.509 +        acl.internal.pos_x=acl.internal.pos_y=0;
 138.510 +        acl.pattern_x=acl.source_x=acl.pattern_y=acl.source_y=0;
 138.511 +        acl.status = ACL_XYST;
 138.512 +        if ((!(acl.internal.ctrl_routing&7) || (acl.internal.ctrl_routing&4)) && !(acl.internal.ctrl_routing&0x40)) acl.status |= ACL_SSO;
 138.513 +        
 138.514 +        if (et4000w32_wrap_x[acl.internal.pattern_wrap&7])
 138.515 +        {
 138.516 +                acl.pattern_x=acl.pattern_addr&et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 138.517 +                acl.pattern_addr&=~et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 138.518 +        }
 138.519 +        acl.pattern_back=acl.pattern_addr;
 138.520 +        if (!(acl.internal.pattern_wrap&0x40))
 138.521 +        {
 138.522 +                acl.pattern_y=(acl.pattern_addr/(et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1))&(et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1);
 138.523 +                acl.pattern_back&=~(((et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1)*et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])-1);
 138.524 +        }
 138.525 +        acl.pattern_x_back=acl.pattern_x;
 138.526 +        
 138.527 +        if (et4000w32_wrap_x[acl.internal.source_wrap&7])
 138.528 +        {
 138.529 +                acl.source_x=acl.source_addr&et4000w32_wrap_x[acl.internal.source_wrap&7];
 138.530 +                acl.source_addr&=~et4000w32_wrap_x[acl.internal.source_wrap&7];
 138.531 +        }
 138.532 +        acl.source_back=acl.source_addr;
 138.533 +        if (!(acl.internal.source_wrap&0x40))
 138.534 +        {
 138.535 +                acl.source_y=(acl.source_addr/(et4000w32_wrap_x[acl.internal.source_wrap&7]+1))&(et4000w32_wrap_y[(acl.internal.source_wrap>>4)&7]-1);
 138.536 +                acl.source_back&=~(((et4000w32_wrap_x[acl.internal.source_wrap&7]+1)*et4000w32_wrap_y[(acl.internal.source_wrap>>4)&7])-1);
 138.537 +        }
 138.538 +        acl.source_x_back=acl.source_x;
 138.539 +
 138.540 +        et4000w32_max_x[2]=((acl.internal.pixel_depth&0x30)==0x20)?3:4;
 138.541 +        
 138.542 +        acl.internal.count_x += (acl.internal.pixel_depth>>4)&3;
 138.543 +        acl.cpu_dat_pos=0;
 138.544 +        acl.cpu_dat=0;
 138.545 +        
 138.546 +        acl.pix_pos=0;
 138.547 +}
 138.548 +
 138.549 +void et4000w32_incx(int c)
 138.550 +{
 138.551 +        acl.dest_addr+=c;
 138.552 +        acl.pattern_x+=c;
 138.553 +        acl.source_x +=c;
 138.554 +        acl.mix_addr +=c;
 138.555 +        if (acl.pattern_x>=et4000w32_max_x[acl.internal.pattern_wrap&7])
 138.556 +           acl.pattern_x -=et4000w32_max_x[acl.internal.pattern_wrap&7];
 138.557 +        if (acl.source_x >=et4000w32_max_x[acl.internal.source_wrap &7])
 138.558 +           acl.source_x  -=et4000w32_max_x[acl.internal.source_wrap &7];
 138.559 +}
 138.560 +void et4000w32_decx(int c)
 138.561 +{
 138.562 +        acl.dest_addr-=c;
 138.563 +        acl.pattern_x-=c;
 138.564 +        acl.source_x -=c;
 138.565 +        acl.mix_addr -=c;
 138.566 +        if (acl.pattern_x<0)
 138.567 +           acl.pattern_x +=et4000w32_max_x[acl.internal.pattern_wrap&7];
 138.568 +        if (acl.source_x <0)
 138.569 +           acl.source_x  +=et4000w32_max_x[acl.internal.source_wrap &7];
 138.570 +}
 138.571 +void et4000w32_incy()
 138.572 +{
 138.573 +        acl.pattern_addr+=acl.internal.pattern_off+1;
 138.574 +        acl.source_addr +=acl.internal.source_off +1;
 138.575 +        acl.mix_addr    +=acl.internal.mix_off    +1;
 138.576 +        acl.dest_addr   +=acl.internal.dest_off   +1;
 138.577 +        acl.pattern_y++;
 138.578 +        if (acl.pattern_y == et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])
 138.579 +        {
 138.580 +                acl.pattern_y = 0;
 138.581 +                acl.pattern_addr = acl.pattern_back;
 138.582 +        }
 138.583 +        acl.source_y++;
 138.584 +        if (acl.source_y == et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7])
 138.585 +        {
 138.586 +                acl.source_y = 0;
 138.587 +                acl.source_addr = acl.source_back;
 138.588 +        }
 138.589 +}
 138.590 +void et4000w32_decy()
 138.591 +{
 138.592 +        acl.pattern_addr-=acl.internal.pattern_off+1;
 138.593 +        acl.source_addr -=acl.internal.source_off +1;
 138.594 +        acl.mix_addr    -=acl.internal.mix_off    +1;
 138.595 +        acl.dest_addr   -=acl.internal.dest_off   +1;
 138.596 +        acl.pattern_y--;
 138.597 +        if (acl.pattern_y<0 && !(acl.internal.pattern_wrap&0x40))
 138.598 +        {
 138.599 +                acl.pattern_y=et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1;
 138.600 +                acl.pattern_addr=acl.pattern_back+(et4000w32_wrap_x[acl.internal.pattern_wrap&7]*(et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1));
 138.601 +        }
 138.602 +        acl.source_y--;
 138.603 +        if (acl.source_y<0 && !(acl.internal.source_wrap&0x40))
 138.604 +        {
 138.605 +                acl.source_y =et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7]-1;
 138.606 +                acl.source_addr =acl.source_back +(et4000w32_wrap_x[acl.internal.source_wrap&7] *(et4000w32_wrap_y[(acl.internal.source_wrap>>4)&7]-1));;
 138.607 +        }
 138.608 +}
 138.609 +
 138.610 +void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input)
 138.611 +{
 138.612 +        int c,d;
 138.613 +        uint8_t pattern,source,dest,out;
 138.614 +        uint8_t rop;
 138.615 +        int mixdat;
 138.616 +
 138.617 +        if (!(acl.status & ACL_XYST)) return;
 138.618 +//        if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr);
 138.619 +        //pclog("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y);
 138.620 +        if (acl.internal.xy_dir&0x80) /*Line draw*/
 138.621 +        {
 138.622 +                while (count--)
 138.623 +                {
 138.624 +                        if (bltout) pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y);
 138.625 +                        pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF];
 138.626 +                        source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF];
 138.627 +                        if (bltout) pclog("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF);
 138.628 +                        if (cpu_input==2)
 138.629 +                        {
 138.630 +                                source=sdat&0xFF;
 138.631 +                                sdat>>=8;
 138.632 +                        }
 138.633 +                        dest=vram[acl.dest_addr   &0x1FFFFF];
 138.634 +                        out=0;
 138.635 +                        if (bltout) pclog("%06X   ",acl.dest_addr);
 138.636 +                        if ((acl.internal.ctrl_routing&0xA)==8)
 138.637 +                        {
 138.638 +                                mixdat = vram[(acl.mix_addr>>3)&0x1FFFFF] & (1<<(acl.mix_addr&7));
 138.639 +                                if (bltout) pclog("%06X %02X  ",acl.mix_addr,vram[(acl.mix_addr>>3)&0x1FFFFF]);
 138.640 +                        }
 138.641 +                        else
 138.642 +                        {
 138.643 +                                mixdat = mix & 1;
 138.644 +                                mix>>=1; mix|=0x80000000;
 138.645 +                        }
 138.646 +                        acl.mix_addr++;
 138.647 +                        rop = (mixdat) ? acl.internal.rop_fg:acl.internal.rop_bg;
 138.648 +                        for (c=0;c<8;c++)
 138.649 +                        {
 138.650 +                                d=(dest & (1<<c)) ? 1:0;
 138.651 +                                if (source & (1<<c))  d|=2;
 138.652 +                                if (pattern & (1<<c)) d|=4;
 138.653 +                                if (rop & (1<<d)) out|=(1<<c);
 138.654 +                        }
 138.655 +                        if (bltout) pclog("%06X = %02X\n",acl.dest_addr&0x1FFFFF,out);
 138.656 +                        if (!(acl.internal.ctrl_routing&0x40))
 138.657 +                        {
 138.658 +                                vram[acl.dest_addr&0x1FFFFF]=out;
 138.659 +                                changedvram[(acl.dest_addr&0x1FFFFF)>>10]=changeframecount;
 138.660 +                        }
 138.661 +                        else
 138.662 +                        {
 138.663 +                                acl.cpu_dat|=((uint64_t)out<<(acl.cpu_dat_pos*8));
 138.664 +                                acl.cpu_dat_pos++;
 138.665 +                        }
 138.666 +                        
 138.667 +//                        pclog("%i %i\n",acl.pix_pos,(acl.internal.pixel_depth>>4)&3);
 138.668 +                        acl.pix_pos++;
 138.669 +                        acl.internal.pos_x++;
 138.670 +                        if (acl.pix_pos<=((acl.internal.pixel_depth>>4)&3))
 138.671 +                        {
 138.672 +                                if (acl.internal.xy_dir&1) et4000w32_decx(1);
 138.673 +                                else                       et4000w32_incx(1);
 138.674 +                        }
 138.675 +                        else
 138.676 +                        {
 138.677 +                                if (acl.internal.xy_dir&1) et4000w32_incx((acl.internal.pixel_depth>>4)&3);
 138.678 +                                else                       et4000w32_decx((acl.internal.pixel_depth>>4)&3);
 138.679 +                                acl.pix_pos=0;
 138.680 +                                /*Next pixel*/
 138.681 +                                switch (acl.internal.xy_dir&7)
 138.682 +                                {
 138.683 +                                        case 0: case 1: /*Y+*/
 138.684 +                                        et4000w32_incy();
 138.685 +                                        acl.internal.pos_y++;
 138.686 +                                        acl.internal.pos_x-=((acl.internal.pixel_depth>>4)&3)+1;
 138.687 +                                        break;
 138.688 +                                        case 2: case 3: /*Y-*/
 138.689 +                                        et4000w32_decy();
 138.690 +                                        acl.internal.pos_y++;
 138.691 +                                        acl.internal.pos_x-=((acl.internal.pixel_depth>>4)&3)+1;
 138.692 +                                        break;
 138.693 +                                        case 4: case 6: /*X+*/
 138.694 +                                        et4000w32_incx(((acl.internal.pixel_depth>>4)&3)+1);
 138.695 +                                        //acl.internal.pos_x++;
 138.696 +                                        break;
 138.697 +                                        case 5: case 7: /*X-*/
 138.698 +                                        et4000w32_decx(((acl.internal.pixel_depth>>4)&3)+1);
 138.699 +                                        //acl.internal.pos_x++;
 138.700 +                                        break;
 138.701 +                                }
 138.702 +                                acl.internal.error+=acl.internal.dmin;
 138.703 +                                if (acl.internal.error > acl.internal.dmaj)
 138.704 +                                {
 138.705 +                                        acl.internal.error-=acl.internal.dmaj;
 138.706 +                                        switch (acl.internal.xy_dir&7)
 138.707 +                                        {
 138.708 +                                                case 0: case 2: /*X+*/
 138.709 +                                                et4000w32_incx(((acl.internal.pixel_depth>>4)&3)+1);
 138.710 +                                                acl.internal.pos_x++;
 138.711 +                                                break;
 138.712 +                                                case 1: case 3: /*X-*/
 138.713 +                                                et4000w32_decx(((acl.internal.pixel_depth>>4)&3)+1);
 138.714 +                                                acl.internal.pos_x++;
 138.715 +                                                break;
 138.716 +                                                case 4: case 5: /*Y+*/
 138.717 +                                                et4000w32_incy();
 138.718 +                                                acl.internal.pos_y++;
 138.719 +                                                break;
 138.720 +                                                case 6: case 7: /*Y-*/
 138.721 +                                                et4000w32_decy();
 138.722 +                                                acl.internal.pos_y++;
 138.723 +                                                break;
 138.724 +                                        }
 138.725 +                                }
 138.726 +                                if (acl.internal.pos_x > acl.internal.count_x ||
 138.727 +                                    acl.internal.pos_y > acl.internal.count_y)
 138.728 +                                {
 138.729 +                                        acl.status = 0;
 138.730 +//                                        pclog("Blit line over\n");
 138.731 +                                        return;
 138.732 +                                }
 138.733 +                        }
 138.734 +                }
 138.735 +        }
 138.736 +        else
 138.737 +        {
 138.738 +                while (count--)
 138.739 +                {
 138.740 +                        if (bltout) pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y);
 138.741 +                        
 138.742 +                        pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF];
 138.743 +                        source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF];
 138.744 +                        if (bltout) pclog("%i %06X %06X %02X %02X  ",acl.pattern_y,(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF,pattern,source);
 138.745 +
 138.746 +                        if (cpu_input==2)
 138.747 +                        {
 138.748 +                                source=sdat&0xFF;
 138.749 +                                sdat>>=8;
 138.750 +                        }
 138.751 +                        dest=vram[acl.dest_addr   &0x1FFFFF];
 138.752 +                        out=0;
 138.753 +                        if (bltout) pclog("%06X %02X  %i %08X %08X  ",dest,acl.dest_addr,mix&1,mix,acl.mix_addr);
 138.754 +                        if ((acl.internal.ctrl_routing&0xA)==8)
 138.755 +                        {
 138.756 +                                mixdat = vram[(acl.mix_addr>>3)&0x1FFFFF] & (1<<(acl.mix_addr&7));
 138.757 +                                if (bltout) pclog("%06X %02X  ",acl.mix_addr,vram[(acl.mix_addr>>3)&0x1FFFFF]);
 138.758 +                        }
 138.759 +                        else
 138.760 +                        {
 138.761 +                                mixdat = mix & 1;
 138.762 +                                mix>>=1; mix|=0x80000000;
 138.763 +                        }
 138.764 +
 138.765 +                        rop = (mixdat) ? acl.internal.rop_fg:acl.internal.rop_bg;
 138.766 +                        for (c=0;c<8;c++)
 138.767 +                        {
 138.768 +                                d=(dest & (1<<c)) ? 1:0;
 138.769 +                                if (source & (1<<c))  d|=2;
 138.770 +                                if (pattern & (1<<c)) d|=4;
 138.771 +                                if (rop & (1<<d)) out|=(1<<c);
 138.772 +                        }
 138.773 +                        if (bltout) pclog("%06X = %02X\n",acl.dest_addr&0x1FFFFF,out);
 138.774 +                        if (!(acl.internal.ctrl_routing&0x40))
 138.775 +                        {
 138.776 +                                vram[acl.dest_addr&0x1FFFFF]=out;
 138.777 +                                changedvram[(acl.dest_addr&0x1FFFFF)>>10]=changeframecount;
 138.778 +                        }
 138.779 +                        else
 138.780 +                        {
 138.781 +                                acl.cpu_dat|=((uint64_t)out<<(acl.cpu_dat_pos*8));
 138.782 +                                acl.cpu_dat_pos++;
 138.783 +                        }
 138.784 +
 138.785 +                        if (acl.internal.xy_dir&1) et4000w32_decx(1);
 138.786 +                        else                       et4000w32_incx(1);
 138.787 +
 138.788 +                        acl.internal.pos_x++;
 138.789 +                        if (acl.internal.pos_x>acl.internal.count_x)
 138.790 +                        {
 138.791 +                                if (acl.internal.xy_dir&2)
 138.792 +                                {
 138.793 +                                        et4000w32_decy();
 138.794 +                                        acl.mix_back =acl.mix_addr =acl.mix_back -(acl.internal.mix_off +1);
 138.795 +                                        acl.dest_back=acl.dest_addr=acl.dest_back-(acl.internal.dest_off+1);
 138.796 +                                }
 138.797 +                                else
 138.798 +                                {
 138.799 +                                        et4000w32_incy();
 138.800 +                                        acl.mix_back =acl.mix_addr =acl.mix_back +acl.internal.mix_off +1;
 138.801 +                                        acl.dest_back=acl.dest_addr=acl.dest_back+acl.internal.dest_off+1;
 138.802 +                                }
 138.803 +
 138.804 +                                acl.pattern_x = acl.pattern_x_back;
 138.805 +                                acl.source_x  = acl.source_x_back;
 138.806 +
 138.807 +                                acl.internal.pos_y++;
 138.808 +                                acl.internal.pos_x=0;
 138.809 +                                if (acl.internal.pos_y>acl.internal.count_y)
 138.810 +                                {
 138.811 +                                        acl.status = 0;
 138.812 +//                                        pclog("Blit over\n");
 138.813 +                                        return;
 138.814 +                                }
 138.815 +                                if (cpu_input) return;
 138.816 +                                if (acl.internal.ctrl_routing&0x40)
 138.817 +                                {
 138.818 +                                        if (acl.cpu_dat_pos&3) acl.cpu_dat_pos+=4-(acl.cpu_dat_pos&3);
 138.819 +                                        return;
 138.820 +                                }
 138.821 +                        }
 138.822 +                }
 138.823 +        }
 138.824 +}
 138.825 +
 138.826 +
 138.827 +void et4000w32p_cursor_draw(int displine)
 138.828 +{
 138.829 +        int x, offset;
 138.830 +        uint8_t dat;
 138.831 +        offset = svga_hwcursor_latch.xoff;
 138.832 +        for (x = 0; x < 64 - svga_hwcursor_latch.xoff; x += 4)
 138.833 +        {
 138.834 +                dat = vram[svga_hwcursor_latch.addr + (offset >> 2)];
 138.835 +                if (!(dat & 2))          ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 32]  = (dat & 1) ? 0xFFFFFF : 0;
 138.836 +                else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 32] ^= 0xFFFFFF;
 138.837 +                dat >>= 2;
 138.838 +                if (!(dat & 2))          ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 33]  = (dat & 1) ? 0xFFFFFF : 0;
 138.839 +                else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 33] ^= 0xFFFFFF;
 138.840 +                dat >>= 2;
 138.841 +                if (!(dat & 2))          ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 34]  = (dat & 1) ? 0xFFFFFF : 0;
 138.842 +                else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 34] ^= 0xFFFFFF;
 138.843 +                dat >>= 2;
 138.844 +                if (!(dat & 2))          ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 35]  = (dat & 1) ? 0xFFFFFF : 0;
 138.845 +                else if ((dat & 3) == 3) ((uint32_t *)buffer32->line[displine])[svga_hwcursor_latch.x + x + 35] ^= 0xFFFFFF;
 138.846 +                dat >>= 2;
 138.847 +                offset += 4;
 138.848 +        }
 138.849 +        svga_hwcursor_latch.addr += 16;
 138.850 +}
 138.851 +
 138.852 +uint8_t et4000w32p_pci_read(int func, int addr)
 138.853 +{
 138.854 +        pclog("ET4000 PCI read %08X\n", addr);
 138.855 +        switch (addr)
 138.856 +        {
 138.857 +                case 0x00: return 0x0c; /*Tseng Labs*/
 138.858 +                case 0x01: return 0x10;
 138.859 +                
 138.860 +                case 0x02: return 0x06; /*ET4000W32p Rev D*/
 138.861 +                case 0x03: return 0x32;
 138.862 +                
 138.863 +                case 0x04: return 0x03; /*Respond to IO and memory accesses*/
 138.864 +
 138.865 +                case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
 138.866 +                
 138.867 +                case 0x08: return 0; /*Revision ID*/
 138.868 +                case 0x09: return 0; /*Programming interface*/
 138.869 +                
 138.870 +                case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/
 138.871 +                case 0x0b: return 0x03;
 138.872 +                
 138.873 +                case 0x10: return 0x00; /*Linear frame buffer address*/
 138.874 +                case 0x11: return 0x00;
 138.875 +                case 0x12: return crtc[0x5a] & 0x80;
 138.876 +                case 0x13: return crtc[0x59];
 138.877 +
 138.878 +                case 0x30: return 0x01; /*BIOS ROM address*/
 138.879 +                case 0x31: return 0x00;
 138.880 +                case 0x32: return 0x0C;
 138.881 +                case 0x33: return 0x00;
 138.882 +        }
 138.883 +        return 0;
 138.884 +}
 138.885 +
 138.886 +void et4000w32p_pci_write(int func, int addr, uint8_t val)
 138.887 +{
 138.888 +        switch (addr)
 138.889 +        {
 138.890 +                case 0x13: et4000w32p_linearbase = val << 24; et4000w32p_recalcmapping(); break;
 138.891 +        }
 138.892 +}
 138.893 +
 138.894 +int et4000w32p_init()
 138.895 +{
 138.896 +        svga_recalctimings_ex = et4000w32p_recalctimings;
 138.897 +        svga_hwcursor_draw    = et4000w32p_cursor_draw;
 138.898 +        
 138.899 +        io_sethandler(0x210A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.900 +        io_sethandler(0x211A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.901 +        io_sethandler(0x212A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.902 +        io_sethandler(0x213A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.903 +        io_sethandler(0x214A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.904 +        io_sethandler(0x215A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.905 +        io_sethandler(0x216A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.906 +        io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL);
 138.907 +        
 138.908 +        pci_add(et4000w32p_pci_read, et4000w32p_pci_write);
 138.909 +        
 138.910 +        svga_vram_limit = 2 << 20; /*2mb - chip supports 4mb but can't map both 4mb linear frame buffer and accelerator registers*/
 138.911 +        
 138.912 +        vrammask = 0x1fffff;
 138.913 +
 138.914 +        return svga_init();
 138.915 +}
 138.916 +
 138.917 +GFXCARD vid_et4000w32p =
 138.918 +{
 138.919 +        et4000w32p_init,
 138.920 +        /*IO at 3Cx/3Dx*/
 138.921 +        et4000w32p_out,
 138.922 +        et4000w32p_in,
 138.923 +        /*IO at 3Ax/3Bx*/
 138.924 +        video_out_null,
 138.925 +        video_in_null,
 138.926 +
 138.927 +        svga_poll,
 138.928 +        svga_recalctimings,
 138.929 +
 138.930 +        svga_write,
 138.931 +        video_write_null,
 138.932 +        video_write_null,
 138.933 +
 138.934 +        svga_read,
 138.935 +        video_read_null,
 138.936 +        video_read_null
 138.937 +};
 138.938 +
 138.939 +
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/src/vid_et4000w32i.c	Sun Apr 21 14:54:35 2013 +0100
   139.3 @@ -0,0 +1,407 @@
   139.4 +/*The below is (with some removals) a reasonable emulation of the ET4000/W32i blitter.
   139.5 +  Unfortunately the Diamond Stealth 32 is actually an ET4000/W32p! Which has a different
   139.6 +  blitter. If only I'd dug out and looked at the card before trying to emulate it.
   139.7 +
   139.8 +  This might be of use for an attempt at emulating an ET4000/W32i.
   139.9 +  */
  139.10 +#if 0
  139.11 +
  139.12 +#include "ibm.h"
  139.13 +
  139.14 +int et4k_b8000;
  139.15 +
  139.16 +struct
  139.17 +{
  139.18 +        struct
  139.19 +        {
  139.20 +                uint32_t pattern_addr,source_addr,dest_addr;
  139.21 +                uint16_t pattern_off,source_off,dest_off;
  139.22 +                uint8_t vbus,xy_dir;
  139.23 +                uint8_t pattern_wrap,source_wrap;
  139.24 +                uint16_t count_x,count_y;
  139.25 +                uint8_t ctrl_routing,ctrl_reload;
  139.26 +                uint8_t rop_fg,rop_bg;
  139.27 +                uint16_t pos_x,pos_y;
  139.28 +        } queued,internal;
  139.29 +        uint32_t pattern_addr,source_addr,dest_addr;
  139.30 +        uint32_t pattern_back,dest_back;
  139.31 +        int pattern_x,source_x;
  139.32 +        int pattern_x_back;
  139.33 +        int pattern_y,source_y;
  139.34 +        uint8_t status;
  139.35 +        uint32_t cpu_input;
  139.36 +        int cpu_input_num;
  139.37 +} acl;
  139.38 +
  139.39 +#define ACL_WRST 1
  139.40 +#define ACL_RDST 2
  139.41 +#define ACL_XYST 4
  139.42 +#define ACL_SSO  8
  139.43 +
  139.44 +struct
  139.45 +{
  139.46 +        uint32_t base[3];
  139.47 +        uint8_t ctrl;
  139.48 +} mmu;
  139.49 +
  139.50 +void et4000w32_reset()
  139.51 +{
  139.52 +        acl.status=0;
  139.53 +        acl.cpu_input_num=0;
  139.54 +}
  139.55 +
  139.56 +void et4000w32_blit_start();
  139.57 +void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input);
  139.58 +
  139.59 +int et4000w32_vbus[4]={1,2,4,4};
  139.60 +
  139.61 +void et4000w32_mmu_write(uint32_t addr, uint8_t val)
  139.62 +{
  139.63 +        int bank;
  139.64 +        pclog("ET4K write %08X %02X %i %02X %02X %04X(%08X):%08X  %04X %04X %02X %08X\n",addr,val,acl.cpu_input_num,acl.status,acl.internal.ctrl_routing,CS,cs,pc,CS,DI,mmu.ctrl,mmu.base[2]);
  139.65 +        switch (addr&0x6000)
  139.66 +        {
  139.67 +                case 0x0000: /*MMU 0*/
  139.68 +                case 0x2000: /*MMU 1*/
  139.69 +                case 0x4000: /*MMU 2*/
  139.70 +                bank=(addr>>13)&3;
  139.71 +                if (mmu.ctrl&(1<<bank))
  139.72 +                {
  139.73 +                        if (!(acl.status&ACL_XYST))
  139.74 +                        {
  139.75 +//                                pclog("!ACL_XYST\n");
  139.76 +                                /*if ((acl.internal.ctrl_routing&0x30)==0x10) */acl.queued.dest_addr=(addr&0x1FFF)+mmu.base[bank];
  139.77 +                                acl.internal=acl.queued;
  139.78 +                                et4000w32_blit_start();
  139.79 +                                if (!(acl.internal.ctrl_routing&0x37)) et4000w32_blit(0xFFFFFF, ~0, 0, 0);
  139.80 +                                acl.cpu_input_num=0;
  139.81 +                        }
  139.82 +//                        else if (!(acl.internal.ctrl_routing&7)) pclog("ACL_XYST\n");
  139.83 +                        if (acl.internal.ctrl_routing&7)
  139.84 +                        {
  139.85 +                                acl.cpu_input=(acl.cpu_input&~(0xFF<<(acl.cpu_input_num*8)))|(val<<(acl.cpu_input_num*8));
  139.86 +                                acl.cpu_input_num++;
  139.87 +                                if (acl.cpu_input_num == et4000w32_vbus[acl.internal.vbus & 3])
  139.88 +                                {
  139.89 +                                        if ((acl.internal.ctrl_routing&7)==2)
  139.90 +                                           et4000w32_blit(acl.cpu_input_num << 3, acl.cpu_input, 0, 1);
  139.91 +                                        else if ((acl.internal.ctrl_routing&7)==1)
  139.92 +                                           et4000w32_blit(acl.cpu_input_num, ~0, acl.cpu_input, 2);
  139.93 +                                        else
  139.94 +                                           pclog("Bad ET4K routing %i\n",acl.internal.ctrl_routing&7);
  139.95 +                                        acl.cpu_input_num=0;
  139.96 +                                }
  139.97 +                        }
  139.98 +//                        else
  139.99 +//                           pclog("Not ctrl_routing\n");
 139.100 +                }
 139.101 +                else
 139.102 +                {
 139.103 +                        vram[(addr&0x1FFF)+mmu.base[bank]]=val;
 139.104 +                        changedvram[((addr&0x1FFF)+mmu.base[bank])>>10]=changeframecount;
 139.105 +                }
 139.106 +                break;
 139.107 +                case 0x6000:
 139.108 +                switch (addr&0x7FFF)
 139.109 +                {
 139.110 +                        case 0x7F00: mmu.base[0]=(mmu.base[0]&0xFFFFFF00)|val;       break;
 139.111 +                        case 0x7F01: mmu.base[0]=(mmu.base[0]&0xFFFF00FF)|(val<<8);  break;
 139.112 +                        case 0x7F02: mmu.base[0]=(mmu.base[0]&0xFF00FFFF)|(val<<16); break;
 139.113 +                        case 0x7F03: mmu.base[0]=(mmu.base[0]&0x00FFFFFF)|(val<<24); break;
 139.114 +                        case 0x7F04: mmu.base[1]=(mmu.base[1]&0xFFFFFF00)|val;       break;
 139.115 +                        case 0x7F05: mmu.base[1]=(mmu.base[1]&0xFFFF00FF)|(val<<8);  break;
 139.116 +                        case 0x7F06: mmu.base[1]=(mmu.base[1]&0xFF00FFFF)|(val<<16); break;
 139.117 +                        case 0x7F07: mmu.base[1]=(mmu.base[1]&0x00FFFFFF)|(val<<24); break;
 139.118 +                        case 0x7F08: mmu.base[2]=(mmu.base[2]&0xFFFFFF00)|val;       break;
 139.119 +                        case 0x7F09: mmu.base[2]=(mmu.base[2]&0xFFFF00FF)|(val<<8);  break;
 139.120 +                        case 0x7F0A: mmu.base[2]=(mmu.base[2]&0xFF00FFFF)|(val<<16); break;
 139.121 +                        case 0x7F0B: mmu.base[2]=(mmu.base[2]&0x00FFFFFF)|(val<<24); break;
 139.122 +                        case 0x7F13: mmu.ctrl=val; break;
 139.123 +
 139.124 +                        case 0x7F80: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFFFF00)|val;       break;
 139.125 +                        case 0x7F81: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFFFF00FF)|(val<<8);  break;
 139.126 +                        case 0x7F82: acl.queued.pattern_addr=(acl.queued.pattern_addr&0xFF00FFFF)|(val<<16); break;
 139.127 +                        case 0x7F83: acl.queued.pattern_addr=(acl.queued.pattern_addr&0x00FFFFFF)|(val<<24); break;
 139.128 +                        case 0x7F84: acl.queued.source_addr =(acl.queued.source_addr &0xFFFFFF00)|val;       break;
 139.129 +                        case 0x7F85: acl.queued.source_addr =(acl.queued.source_addr &0xFFFF00FF)|(val<<8);  break;
 139.130 +                        case 0x7F86: acl.queued.source_addr =(acl.queued.source_addr &0xFF00FFFF)|(val<<16); break;
 139.131 +                        case 0x7F87: acl.queued.source_addr =(acl.queued.source_addr &0x00FFFFFF)|(val<<24); break;
 139.132 +                        case 0x7F88: acl.queued.pattern_off=(acl.queued.pattern_off&0xFF00)|val;      break;
 139.133 +                        case 0x7F89: acl.queued.pattern_off=(acl.queued.pattern_off&0x00FF)|(val<<8); break;
 139.134 +                        case 0x7F8A: acl.queued.source_off =(acl.queued.source_off &0xFF00)|val;      break;
 139.135 +                        case 0x7F8B: acl.queued.source_off =(acl.queued.source_off &0x00FF)|(val<<8); break;
 139.136 +                        case 0x7F8C: acl.queued.dest_off   =(acl.queued.dest_off   &0xFF00)|val;      break;
 139.137 +                        case 0x7F8D: acl.queued.dest_off   =(acl.queued.dest_off   &0x00FF)|(val<<8); break;
 139.138 +                        case 0x7F8E: acl.queued.vbus=val; break;
 139.139 +                        case 0x7F8F: acl.queued.xy_dir=val; break;
 139.140 +                        case 0x7F90: acl.queued.pattern_wrap=val; break;
 139.141 +                        case 0x7F92: acl.queued.source_wrap=val; break;
 139.142 +                        case 0x7F98: acl.queued.count_x    =(acl.queued.count_x    &0xFF00)|val;      break;
 139.143 +                        case 0x7F99: acl.queued.count_x    =(acl.queued.count_x    &0x00FF)|(val<<8); break;
 139.144 +                        case 0x7F9A: acl.queued.count_y    =(acl.queued.count_y    &0xFF00)|val;      break;
 139.145 +                        case 0x7F9B: acl.queued.count_y    =(acl.queued.count_y    &0x00FF)|(val<<8); break;
 139.146 +                        case 0x7F9C: acl.queued.ctrl_routing=val; break;
 139.147 +                        case 0x7F9D: acl.queued.ctrl_reload =val; break;
 139.148 +                        case 0x7F9E: acl.queued.rop_bg      =val; break;
 139.149 +                        case 0x7F9F: acl.queued.rop_fg      =val; break;
 139.150 +                        case 0x7FA0: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFFFFFF00)|val;       break;
 139.151 +                        case 0x7FA1: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFFFF00FF)|(val<<8);  break;
 139.152 +                        case 0x7FA2: acl.queued.dest_addr   =(acl.queued.dest_addr   &0xFF00FFFF)|(val<<16); break;
 139.153 +                        case 0x7FA3: acl.queued.dest_addr   =(acl.queued.dest_addr   &0x00FFFFFF)|(val<<24);
 139.154 +                        acl.internal=acl.queued;
 139.155 +                        et4000w32_blit_start();
 139.156 +                        acl.cpu_input_num=0;
 139.157 +                        if (!(acl.queued.ctrl_routing&0x37))
 139.158 +                        {
 139.159 +                                et4000w32_blit(0xFFFFFF, ~0, 0, 0);
 139.160 +                        }
 139.161 +                        break;
 139.162 +                }
 139.163 +                break;
 139.164 +        }
 139.165 +}
 139.166 +
 139.167 +uint8_t et4000w32_mmu_read(uint32_t addr)
 139.168 +{
 139.169 +        int bank;
 139.170 +        pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc);
 139.171 +        switch (addr&0x6000)
 139.172 +        {
 139.173 +                case 0x0000: /*MMU 0*/
 139.174 +                case 0x2000: /*MMU 1*/
 139.175 +                case 0x4000: /*MMU 2*/
 139.176 +                bank=(addr>>13)&3;
 139.177 +                if (mmu.ctrl&(1<<bank))
 139.178 +                {
 139.179 +                        /*???*/
 139.180 +                        return 0xFF;
 139.181 +                }
 139.182 +                return vram[(addr&0x1FFF)+mmu.base[bank]];
 139.183 +                case 0x6000:
 139.184 +                switch (addr&0x7FFF)
 139.185 +                {
 139.186 +                        case 0x7F00: return mmu.base[0];
 139.187 +                        case 0x7F01: return mmu.base[0]>>8;
 139.188 +                        case 0x7F02: return mmu.base[0]>>16;
 139.189 +                        case 0x7F03: return mmu.base[0]>>24;
 139.190 +                        case 0x7F04: return mmu.base[1];
 139.191 +                        case 0x7F05: return mmu.base[1]>>8;
 139.192 +                        case 0x7F06: return mmu.base[1]>>16;
 139.193 +                        case 0x7F07: return mmu.base[1]>>24;
 139.194 +                        case 0x7F08: return mmu.base[2];
 139.195 +                        case 0x7F09: return mmu.base[2]>>8;
 139.196 +                        case 0x7F0A: return mmu.base[2]>>16;
 139.197 +                        case 0x7F0B: return mmu.base[2]>>24;
 139.198 +                        case 0x7F13: return mmu.ctrl;
 139.199 +
 139.200 +                        case 0x7F36:
 139.201 +//                        if (acl.internal.pos_x!=acl.internal.count_x || acl.internal.pos_y!=acl.internal.count_y) return acl.status | ACL_XYST;
 139.202 +                        return acl.status & ~(ACL_XYST | ACL_SSO);
 139.203 +                        case 0x7F80: return acl.internal.pattern_addr;
 139.204 +                        case 0x7F81: return acl.internal.pattern_addr>>8;
 139.205 +                        case 0x7F82: return acl.internal.pattern_addr>>16;
 139.206 +                        case 0x7F83: return acl.internal.pattern_addr>>24;
 139.207 +                        case 0x7F84: return acl.internal.source_addr;
 139.208 +                        case 0x7F85: return acl.internal.source_addr>>8;
 139.209 +                        case 0x7F86: return acl.internal.source_addr>>16;
 139.210 +                        case 0x7F87: return acl.internal.source_addr>>24;
 139.211 +                        case 0x7F88: return acl.internal.pattern_off;
 139.212 +                        case 0x7F89: return acl.internal.pattern_off>>8;
 139.213 +                        case 0x7F8A: return acl.internal.source_off;
 139.214 +                        case 0x7F8B: return acl.internal.source_off>>8;
 139.215 +                        case 0x7F8C: return acl.internal.dest_off;
 139.216 +                        case 0x7F8D: return acl.internal.dest_off>>8;
 139.217 +                        case 0x7F8E: return acl.internal.vbus;
 139.218 +                        case 0x7F8F: return acl.internal.xy_dir;
 139.219 +                        case 0x7F90: return acl.internal.pattern_wrap;
 139.220 +                        case 0x7F92: return acl.internal.source_wrap;
 139.221 +                        case 0x7F98: return acl.internal.count_x;
 139.222 +                        case 0x7F99: return acl.internal.count_x>>8;
 139.223 +                        case 0x7F9A: return acl.internal.count_y;
 139.224 +                        case 0x7F9B: return acl.internal.count_y>>8;
 139.225 +                        case 0x7F9C: return acl.internal.ctrl_routing;
 139.226 +                        case 0x7F9D: return acl.internal.ctrl_reload;
 139.227 +                        case 0x7F9E: return acl.internal.rop_bg;
 139.228 +                        case 0x7F9F: return acl.internal.rop_fg;
 139.229 +                        case 0x7FA0: return acl.internal.dest_addr;
 139.230 +                        case 0x7FA1: return acl.internal.dest_addr>>8;
 139.231 +                        case 0x7FA2: return acl.internal.dest_addr>>16;
 139.232 +                        case 0x7FA3: return acl.internal.dest_addr>>24;
 139.233 +                }
 139.234 +                return 0xFF;
 139.235 +        }
 139.236 +}
 139.237 +
 139.238 +int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF};
 139.239 +int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
 139.240 +
 139.241 +void et4000w32_blit_start()
 139.242 +{
 139.243 +        pclog("Blit - %08X %08X %08X (%i,%i) %i  %i %i  %02X %02X  %02X\n",acl.internal.pattern_addr,acl.internal.source_addr,acl.internal.dest_addr,acl.internal.dest_addr%640,acl.internal.dest_addr/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing);
 139.244 +        acl.pattern_addr=acl.internal.pattern_addr;
 139.245 +        acl.source_addr =acl.internal.source_addr;
 139.246 +        acl.dest_addr   =acl.internal.dest_addr;
 139.247 +        acl.dest_back   =acl.dest_addr;
 139.248 +        acl.internal.pos_x=acl.internal.pos_y=0;
 139.249 +        acl.pattern_x=acl.source_x=acl.pattern_y=acl.source_y=0;
 139.250 +        acl.status = ACL_XYST;
 139.251 +        if (!(acl.internal.ctrl_routing&7) || (acl.internal.ctrl_routing&4)) acl.status |= ACL_SSO;
 139.252 +        if (et4000w32_wrap_x[acl.internal.pattern_wrap&7])
 139.253 +        {
 139.254 +                acl.pattern_x=acl.pattern_addr&et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 139.255 +                acl.pattern_addr&=~et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 139.256 +        }
 139.257 +        if (!(acl.internal.pattern_wrap&0x80))
 139.258 +        {
 139.259 +                acl.pattern_y=(acl.pattern_addr/(et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1))&(et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7]-1);
 139.260 +                acl.pattern_addr&=~(((et4000w32_wrap_x[acl.internal.pattern_wrap&7]+1)*et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])-1);
 139.261 +        }
 139.262 +        acl.pattern_x_back=acl.pattern_x;
 139.263 +        acl.pattern_back=acl.pattern_addr;
 139.264 +}
 139.265 +
 139.266 +void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input)
 139.267 +{
 139.268 +        int c,d;
 139.269 +        uint8_t pattern,source,dest,out;
 139.270 +        uint8_t rop;
 139.271 +
 139.272 +//        if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr);
 139.273 +//        pclog("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y);
 139.274 +        while (count--)
 139.275 +        {
 139.276 +                pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y);
 139.277 +                if (acl.internal.xy_dir&1)
 139.278 +                {
 139.279 +                        pattern=vram[(acl.pattern_addr-acl.pattern_x)&0x1FFFFF];
 139.280 +                        source =vram[(acl.source_addr -acl.source_x) &0x1FFFFF];
 139.281 +                        pclog("%06X %06X ",(acl.pattern_addr-acl.pattern_x)&0x1FFFFF,(acl.source_addr -acl.source_x) &0x1FFFFF);
 139.282 +                }
 139.283 +                else
 139.284 +                {
 139.285 +                        pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF];
 139.286 +                        source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF];
 139.287 +                        pclog("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF);
 139.288 +                }
 139.289 +                if (cpu_input==2)
 139.290 +                {
 139.291 +                        source=sdat&0xFF;
 139.292 +                        sdat>>=8;
 139.293 +                }
 139.294 +                dest=vram[acl.dest_addr   &0x1FFFFF];
 139.295 +                out=0;
 139.296 +                pclog("%06X %i %08X   ",acl.dest_addr,mix&1,mix);
 139.297 +                rop = (mix & 1) ? acl.internal.rop_fg:acl.internal.rop_bg;
 139.298 +                mix>>=1; mix|=0x80000000;
 139.299 +                for (c=0;c<8;c++)
 139.300 +                {
 139.301 +                        d=(dest & (1<<c)) ? 1:0;
 139.302 +                        if (source & (1<<c))  d|=2;
 139.303 +                        if (pattern & (1<<c)) d|=4;
 139.304 +                        if (rop & (1<<d)) out|=(1<<c);
 139.305 +                }
 139.306 +                pclog("%06X = %02X\n",acl.dest_addr&0x1FFFFF,out);
 139.307 +                vram[acl.dest_addr&0x1FFFFF]=out;
 139.308 +                changedvram[(acl.dest_addr&0x1FFFFF)>>10]=changeframecount;
 139.309 +
 139.310 +                acl.pattern_x++;
 139.311 +                acl.pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 139.312 +                acl.source_x++;
 139.313 +                acl.source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7];
 139.314 +                if (acl.internal.xy_dir&1) acl.dest_addr--;
 139.315 +                else                       acl.dest_addr++;
 139.316 +
 139.317 +                acl.internal.pos_x++;
 139.318 +                if (acl.internal.pos_x>acl.internal.count_x)
 139.319 +                {
 139.320 +                        if (acl.internal.xy_dir&2)
 139.321 +                        {
 139.322 +                                acl.pattern_addr-=(acl.internal.pattern_off+1);
 139.323 +                                acl.source_addr -=(acl.internal.source_off +1);
 139.324 +                                acl.dest_back=acl.dest_addr=acl.dest_back-(acl.internal.dest_off+1);
 139.325 +                        }
 139.326 +                        else
 139.327 +                        {
 139.328 +                                acl.pattern_addr+=acl.internal.pattern_off+1;
 139.329 +                                acl.source_addr +=acl.internal.source_off +1;
 139.330 +                                acl.dest_back=acl.dest_addr=acl.dest_back+acl.internal.dest_off+1;
 139.331 +                        }
 139.332 +                        acl.pattern_x = acl.pattern_x_back;
 139.333 +                        acl.source_x = 0;
 139.334 +                        acl.pattern_y++;
 139.335 +                        if (acl.pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])
 139.336 +                        {
 139.337 +                                acl.pattern_y=0;
 139.338 +                                acl.pattern_addr=acl.pattern_back;
 139.339 +                        }
 139.340 +                        acl.source_y++;
 139.341 +                        if (acl.source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7])
 139.342 +                        {
 139.343 +                                acl.source_y=0;
 139.344 +                                acl.source_addr=acl.internal.source_addr;
 139.345 +                        }
 139.346 +
 139.347 +                        acl.internal.pos_y++;
 139.348 +                        if (acl.internal.pos_y>acl.internal.count_y)
 139.349 +                        {
 139.350 +                                acl.status = 0;
 139.351 +                                return;
 139.352 +                        }
 139.353 +                        acl.internal.pos_x=0;
 139.354 +                        if (cpu_input) return;
 139.355 +                }
 139.356 +        }
 139.357 +}
 139.358 +
 139.359 +/*        for (y=0;y<=acl.internal.count_y;y++)
 139.360 +        {
 139.361 +                dest_back=acl.dest_addr;
 139.362 +                for (x=0;x<=acl.internal.count_x;x++)
 139.363 +                {
 139.364 +                        if (acl.internal.xy_dir&1)
 139.365 +                        {
 139.366 +                                pattern=vram[(acl.pattern_addr-pattern_x)&0x1FFFFF];
 139.367 +                                source =vram[(acl.source_addr -source_x) &0x1FFFFF];
 139.368 +                        }
 139.369 +                        else
 139.370 +                        {
 139.371 +                                pattern=vram[(acl.pattern_addr+pattern_x)&0x1FFFFF];
 139.372 +                                source =vram[(acl.source_addr +source_x) &0x1FFFFF];
 139.373 +                        }
 139.374 +                        dest=vram[acl.dest_addr   &0x1FFFFF];
 139.375 +                        out=0;
 139.376 +                        for (c=0;c<8;c++)
 139.377 +                        {
 139.378 +                                d=(dest&(1<<c))?1:0;
 139.379 +                                if (source&(1<<c))  d|=2;
 139.380 +                                if (pattern&(1<<c)) d|=4;
 139.381 +                                if (acl.internal.rop_bg&(1<<d)) out|=(1<<c);
 139.382 +                        }
 139.383 +                        vram[acl.dest_addr&0x1FFFFF]=out;
 139.384 +                        changedvram[(acl.dest_addr&0x1FFFFF)>>10]=changeframecount;
 139.385 +
 139.386 +                        pattern_x++;
 139.387 +                        pattern_x&=et4000w32_wrap_x[acl.internal.pattern_wrap&7];
 139.388 +                        source_x++;
 139.389 +                        source_x &=et4000w32_wrap_x[acl.internal.source_wrap&7];
 139.390 +                        if (acl.internal.xy_dir&1) acl.dest_addr--;
 139.391 +                        else                       acl.dest_addr++;
 139.392 +                }
 139.393 +                acl.pattern_addr+=acl.internal.pattern_off+1;
 139.394 +                acl.source_addr +=acl.internal.source_off+1;
 139.395 +                acl.dest_addr=dest_back+acl.internal.dest_off+1;
 139.396 +                pattern_y++;
 139.397 +                if (pattern_y==et4000w32_wrap_y[(acl.internal.pattern_wrap>>4)&7])
 139.398 +                {
 139.399 +                        pattern_y=0;
 139.400 +                        acl.pattern_addr=acl.internal.pattern_addr;
 139.401 +                }
 139.402 +                source_y++;
 139.403 +                if (source_y ==et4000w32_wrap_y[(acl.internal.source_wrap >>4)&7])
 139.404 +                {
 139.405 +                        source_y=0;
 139.406 +                        acl.source_addr=acl.internal.source_addr;
 139.407 +                }
 139.408 +        }*/
 139.409 +
 139.410 +#endif
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/src/vid_hercules.c	Sun Apr 21 14:54:35 2013 +0100
   140.3 @@ -0,0 +1,291 @@
   140.4 +/*Hercules emulation*/
   140.5 +#include "ibm.h"
   140.6 +#include "video.h"
   140.7 +
   140.8 +void hercules_recalctimings();
   140.9 +void hercules_write(uint32_t addr, uint8_t val);
  140.10 +uint8_t hercules_read(uint32_t addr);
  140.11 +
  140.12 +static uint8_t hercules_ctrl, hercules_ctrl2, hercules_stat;
  140.13 +uint8_t crtcm[32],crtcmreg;
  140.14 +
  140.15 +void hercules_out(uint16_t addr, uint8_t val)
  140.16 +{
  140.17 +//        pclog("Herc out %04X %02X\n",addr,val);
  140.18 +        switch (addr)
  140.19 +        {
  140.20 +                case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
  140.21 +                crtcmreg = val & 31;
  140.22 +                return;
  140.23 +                case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
  140.24 +                crtcm[crtcmreg] = val;
  140.25 +                if (crtcm[10]==6 && crtcm[11]==7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
  140.26 +                {
  140.27 +                        crtcm[10]=0xB;
  140.28 +                        crtcm[11]=0xC;
  140.29 +                }
  140.30 +                hercules_recalctimings();
  140.31 +                return;
  140.32 +                case 0x3B8:
  140.33 +                hercules_ctrl = val;
  140.34 +                return;
  140.35 +                case 0x3BF:
  140.36 +                hercules_ctrl2 = val;
  140.37 +                video_write_b800 = (val&2) ? hercules_write : video_write_null;
  140.38 +                video_read_b800  = (val&2) ? hercules_read  : video_read_null;
  140.39 +                return;
  140.40 +        }
  140.41 +}
  140.42 +
  140.43 +uint8_t hercules_in(uint16_t addr)
  140.44 +{
  140.45 + //       pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX);
  140.46 +        switch (addr)
  140.47 +        {
  140.48 +                case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
  140.49 +                return crtcmreg;
  140.50 +                case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
  140.51 +                return crtcm[crtcmreg];
  140.52 +                case 0x3BA:
  140.53 +                return (hercules_stat & 0xF) | ((hercules_stat & 8) << 4);
  140.54 +        }
  140.55 +}
  140.56 +
  140.57 +void hercules_write(uint32_t addr, uint8_t val)
  140.58 +{
  140.59 +//        pclog("Herc write %08X %02X\n",addr,val);
  140.60 +        vram[addr&0xFFFF]=val;
  140.61 +}
  140.62 +
  140.63 +uint8_t hercules_read(uint32_t addr)
  140.64 +{
  140.65 +        return vram[addr&0xFFFF];
  140.66 +}
  140.67 +
  140.68 +void hercules_recalctimings()
  140.69 +{
  140.70 +        disptime=crtc[0]+1;
  140.71 +        dispontime=crtc[1];
  140.72 +        dispofftime=disptime-dispontime;
  140.73 +        dispontime*=MDACONST;
  140.74 +        dispofftime*=MDACONST;
  140.75 +}
  140.76 +
  140.77 +int mdacols[256][2][2];
  140.78 +
  140.79 +static int linepos,displine;
  140.80 +static int vc,sc;
  140.81 +static uint16_t ma,maback,ca;
  140.82 +static int con,coff,cursoron;
  140.83 +static int cgadispon,cgablink;
  140.84 +static int vsynctime,vadj;
  140.85 +
  140.86 +void hercules_poll()
  140.87 +{
  140.88 +        uint16_t ca=(crtcm[15]|(crtcm[14]<<8))&0x3FFF;
  140.89 +        int drawcursor;
  140.90 +        int x,c;
  140.91 +        int oldvc;
  140.92 +        uint8_t chr,attr;
  140.93 +        uint16_t dat,dat2,dat3,dat4;
  140.94 +        int cols[4];
  140.95 +        int col;
  140.96 +        int oldsc;
  140.97 +        int blink;
  140.98 +        if (!linepos)
  140.99 +        {
 140.100 +                //pclog("Poll %i %i\n",vc,sc);
 140.101 +                vidtime+=dispofftime;
 140.102 +                hercules_stat|=1;
 140.103 +                linepos=1;
 140.104 +                oldsc=sc;
 140.105 +                if ((crtcm[8]&3)==3) sc=(sc<<1)&7;
 140.106 +                if (cgadispon)
 140.107 +                {
 140.108 +                        if (displine<firstline)
 140.109 +                        {
 140.110 +                                firstline=displine;
 140.111 +                        }
 140.112 +                        lastline=displine;
 140.113 +                        cols[0]=0;
 140.114 +                        cols[1]=7;
 140.115 +                        if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1))
 140.116 +                        {
 140.117 +                                ca=(sc&3)*0x2000;
 140.118 +                                if ((hercules_ctrl & 0x80) && (hercules_ctrl2 & 2)) ca+=0x8000;
 140.119 +//                                printf("Draw herc %04X\n",ca);
 140.120 +                                for (x=0;x<crtcm[1];x++)
 140.121 +                                {
 140.122 +                                        dat=(vram[((ma<<1)&0x1FFF)+ca]<<8)|vram[((ma<<1)&0x1FFF)+ca+1];
 140.123 +                                        ma++;
 140.124 +                                        for (c=0;c<16;c++)
 140.125 +                                            buffer->line[displine][(x<<4)+c]=(dat&(32768>>c))?7:0;
 140.126 +                                }
 140.127 +                        }
 140.128 +                        else
 140.129 +                        {
 140.130 +                                for (x=0;x<crtcm[1];x++)
 140.131 +                                {
 140.132 +                                        chr=vram[(ma<<1)&0x3FFF];
 140.133 +                                        attr=vram[((ma<<1)+1)&0x3FFF];
 140.134 +                                        drawcursor=((ma==ca) && con && cursoron);
 140.135 +                                        blink=((cgablink&16) && (hercules_ctrl&0x20) && (attr&0x80) && !drawcursor);
 140.136 +                                        if (sc==12 && ((attr&7)==1))
 140.137 +                                        {
 140.138 +                                                for (c=0;c<9;c++)
 140.139 +                                                    buffer->line[displine][(x*9)+c]=mdacols[attr][blink][1];
 140.140 +                                        }
 140.141 +                                        else
 140.142 +                                        {
 140.143 +                                                for (c=0;c<8;c++)
 140.144 +                                                    buffer->line[displine][(x*9)+c]=mdacols[attr][blink][(fontdatm[chr][sc]&(1<<(c^7)))?1:0];
 140.145 +                                                if ((chr&~0x1F)==0xC0) buffer->line[displine][(x*9)+8]=mdacols[attr][blink][fontdatm[chr][sc]&1];
 140.146 +                                                else                   buffer->line[displine][(x*9)+8]=mdacols[attr][blink][0];
 140.147 +                                        }
 140.148 +                                        ma++;
 140.149 +                                        if (drawcursor)
 140.150 +                                        {
 140.151 +                                                for (c=0;c<9;c++)
 140.152 +                                                    buffer->line[displine][(x*9)+c]^=mdacols[attr][0][1];
 140.153 +                                        }
 140.154 +                                }
 140.155 +                        }
 140.156 +                }
 140.157 +                sc=oldsc;
 140.158 +                if (vc==crtcm[7] && !sc)
 140.159 +                {
 140.160 +                        hercules_stat|=8;
 140.161 +//                        printf("VSYNC on %i %i\n",vc,sc);
 140.162 +                }
 140.163 +                displine++;
 140.164 +                if (displine>=500) displine=0;
 140.165 +        }
 140.166 +        else
 140.167 +        {
 140.168 +                vidtime+=dispontime;
 140.169 +                if (cgadispon) hercules_stat&=~1;
 140.170 +                linepos=0;
 140.171 +                if (vsynctime)
 140.172 +                {
 140.173 +                        vsynctime--;
 140.174 +                        if (!vsynctime)
 140.175 +                        {
 140.176 +                                hercules_stat&=~8;
 140.177 +//                                printf("VSYNC off %i %i\n",vc,sc);
 140.178 +                        }
 140.179 +                }
 140.180 +                if (sc==(crtcm[11]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[11]&31)>>1))) { con=0; coff=1; }
 140.181 +                if (vadj)
 140.182 +                {
 140.183 +                        sc++;
 140.184 +                        sc&=31;
 140.185 +                        ma=maback;
 140.186 +                        vadj--;
 140.187 +                        if (!vadj)
 140.188 +                        {
 140.189 +                                cgadispon=1;
 140.190 +                                ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
 140.191 +                                sc=0;
 140.192 +                        }
 140.193 +                }
 140.194 +                else if (sc==crtcm[9] || ((crtcm[8]&3)==3 && sc==(crtcm[9]>>1)))
 140.195 +                {
 140.196 +                        maback=ma;
 140.197 +                        sc=0;
 140.198 +                        oldvc=vc;
 140.199 +                        vc++;
 140.200 +                        vc&=127;
 140.201 +                        if (vc==crtcm[6]) cgadispon=0;
 140.202 +                        if (oldvc==crtcm[4])
 140.203 +                        {
 140.204 +//                                printf("Display over at %i\n",displine);
 140.205 +                                vc=0;
 140.206 +                                vadj=crtcm[5];
 140.207 +                                if (!vadj) cgadispon=1;
 140.208 +                                if (!vadj) ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
 140.209 +                                if ((crtcm[10]&0x60)==0x20) cursoron=0;
 140.210 +                                else                        cursoron=cgablink&16;
 140.211 +                        }
 140.212 +                        if (vc==crtcm[7])
 140.213 +                        {
 140.214 +                                cgadispon=0;
 140.215 +                                displine=0;
 140.216 +                                vsynctime=16;//(crtcm[3]>>4)+1;
 140.217 +                                if (crtcm[7])
 140.218 +                                {
 140.219 +//                                        printf("Lastline %i Firstline %i  %i\n",lastline,firstline,lastline-firstline);
 140.220 +                                        if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1)) x = crtcm[1] << 4;
 140.221 +                                        else                                             x = crtcm[1] * 9;
 140.222 +                                        lastline++;
 140.223 +                                        if (x!=xsize || (lastline-firstline)!=ysize)
 140.224 +                                        {
 140.225 +                                                xsize=x;
 140.226 +                                                ysize=lastline-firstline;
 140.227 +//                                                printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
 140.228 +                                                if (xsize<64) xsize=656;
 140.229 +                                                if (ysize<32) ysize=200;
 140.230 +                                                updatewindowsize(xsize,ysize);
 140.231 +                                        }
 140.232 +                                startblit();
 140.233 +                                        video_blit_memtoscreen_8(0, firstline, xsize, ysize);
 140.234 +                                endblit();
 140.235 +                                        frames++;
 140.236 +                                        if ((hercules_ctrl & 2) && (hercules_ctrl2 & 1))
 140.237 +                                        {
 140.238 +                                                video_res_x = crtcm[1] * 16;
 140.239 +                                                video_res_y = crtcm[6] * 4;
 140.240 +                                                video_bpp = 1;
 140.241 +                                        }
 140.242 +                                        else
 140.243 +                                        {
 140.244 +                                                video_res_x = crtcm[1];
 140.245 +                                                video_res_y = crtcm[6];
 140.246 +                                                video_bpp = 0;
 140.247 +                                        }
 140.248 +                                }
 140.249 +                                firstline=1000;
 140.250 +                                lastline=0;
 140.251 +                                cgablink++;
 140.252 +                        }
 140.253 +                }
 140.254 +                else
 140.255 +                {
 140.256 +                        sc++;
 140.257 +                        sc&=31;
 140.258 +                        ma=maback;
 140.259 +                }
 140.260 +                if ((sc==(crtcm[10]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[10]&31)>>1))))
 140.261 +                {
 140.262 +                        con=1;
 140.263 +//                        printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
 140.264 +                }
 140.265 +        }
 140.266 +}
 140.267 +
 140.268 +int hercules_init()
 140.269 +{
 140.270 +        mem_sethandler(0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL);
 140.271 +        return 0;
 140.272 +}
 140.273 +
 140.274 +GFXCARD vid_hercules =
 140.275 +{
 140.276 +        hercules_init,
 140.277 +        /*IO at 3Cx/3Dx*/
 140.278 +        video_out_null,
 140.279 +        video_in_null,
 140.280 +        /*IO at 3Ax/3Bx*/
 140.281 +        hercules_out,
 140.282 +        hercules_in,
 140.283 +
 140.284 +        hercules_poll,
 140.285 +        hercules_recalctimings,
 140.286 +
 140.287 +        video_write_null,
 140.288 +        hercules_write,
 140.289 +        video_write_null,
 140.290 +
 140.291 +        video_read_null,
 140.292 +        hercules_read,
 140.293 +        video_read_null
 140.294 +};
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/src/vid_icd2061.c	Sun Apr 21 14:54:35 2013 +0100
   141.3 @@ -0,0 +1,74 @@
   141.4 +/*PCem v0.7 by Tom Walker
   141.5 +
   141.6 +  ICD2061 clock generator emulation
   141.7 +  Used by ET4000w32/p (Diamond Stealth 32)*/
   141.8 +#include "ibm.h"
   141.9 +#include "vid_icd2061.h"
  141.10 +
  141.11 +static int icd2061_state;
  141.12 +static int icd2061_status = 0;
  141.13 +static int icd2061_pos = 0;
  141.14 +static int icd2061_unlock = 0;
  141.15 +static uint32_t icd2061_data;
  141.16 +
  141.17 +static double icd2061_freq[4];
  141.18 +static uint32_t icd2061_ctrl;
  141.19 +
  141.20 +void icd2061_write(int val)
  141.21 +{
  141.22 +        int q, p, m, i, a;
  141.23 +        if ((val & 1) && !(icd2061_state & 1))
  141.24 +        {
  141.25 +                pclog("ICD2061 write %02X %i %08X %i\n", val, icd2061_unlock, icd2061_data, icd2061_pos);
  141.26 +                if (!icd2061_status)
  141.27 +                {
  141.28 +                        if (val & 2) icd2061_unlock++;
  141.29 +                        else         
  141.30 +                        {
  141.31 +                                if (icd2061_unlock >= 5)
  141.32 +                                {
  141.33 +                                        icd2061_status = 1;
  141.34 +                                        icd2061_pos = 0;
  141.35 +                                }
  141.36 +                                else
  141.37 +                                   icd2061_unlock = 0;
  141.38 +                        }
  141.39 +                }
  141.40 +                else if (val & 1)
  141.41 +                {
  141.42 +                        icd2061_data = (icd2061_data >> 1) | (((val & 2) ? 1 : 0) << 24);
  141.43 +                        icd2061_pos++;
  141.44 +                        if (icd2061_pos == 26)
  141.45 +                        {
  141.46 +                                pclog("ICD2061 data - %08X\n", icd2061_data);
  141.47 +                                a = (icd2061_data >> 21) & 0x7;                                
  141.48 +                                if (!(a & 4))
  141.49 +                                {
  141.50 +                                        q = (icd2061_data & 0x7f) - 2;
  141.51 +                                        m = 1 << ((icd2061_data >> 7) & 0x7);
  141.52 +                                        p = ((icd2061_data >> 10) & 0x7f) - 3;
  141.53 +                                        i = (icd2061_data >> 17) & 0xf;
  141.54 +                                        pclog("p %i q %i m %i\n", p, q, m);
  141.55 +                                        if (icd2061_ctrl & (1 << a))
  141.56 +                                           p <<= 1;
  141.57 +                                        icd2061_freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m;
  141.58 +                                        pclog("ICD2061 freq %i = %f\n", a, icd2061_freq[a]);
  141.59 +                                }
  141.60 +                                else if (a == 6)
  141.61 +                                {
  141.62 +                                        icd2061_ctrl = val;
  141.63 +                                        pclog("ICD2061 ctrl = %08X\n", val);
  141.64 +                                }
  141.65 +                                icd2061_unlock = icd2061_data = 0;
  141.66 +                                icd2061_status = 0;
  141.67 +                        }
  141.68 +                }
  141.69 +        }
  141.70 +        icd2061_state = val;
  141.71 +}
  141.72 +
  141.73 +double icd2061_getfreq(int i)
  141.74 +{
  141.75 +        pclog("Return freq %f\n", icd2061_freq[i]);
  141.76 +        return icd2061_freq[i];
  141.77 +}
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/src/vid_icd2061.h	Sun Apr 21 14:54:35 2013 +0100
   142.3 @@ -0,0 +1,2 @@
   142.4 +void icd2061_write(int val);
   142.5 +double icd2061_getfreq(int i);
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/src/vid_mda.c	Sun Apr 21 14:54:35 2013 +0100
   143.3 @@ -0,0 +1,254 @@
   143.4 +/*MDA emulation*/
   143.5 +#include "ibm.h"
   143.6 +#include "video.h"
   143.7 +
   143.8 +void mda_recalctimings();
   143.9 +
  143.10 +static uint8_t mda_ctrl,mda_stat;
  143.11 +uint8_t crtcm[32],crtcmreg;
  143.12 +
  143.13 +void mda_out(uint16_t addr, uint8_t val)
  143.14 +{
  143.15 +        switch (addr)
  143.16 +        {
  143.17 +                case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
  143.18 +                crtcmreg = val & 31;
  143.19 +                return;
  143.20 +                case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
  143.21 +                crtcm[crtcmreg] = val;
  143.22 +                if (crtcm[10]==6 && crtcm[11]==7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
  143.23 +                {
  143.24 +                        crtcm[10]=0xB;
  143.25 +                        crtcm[11]=0xC;
  143.26 +                }
  143.27 +                mda_recalctimings();
  143.28 +                return;
  143.29 +                case 0x3B8:
  143.30 +                mda_ctrl = val;
  143.31 +                return;
  143.32 +        }
  143.33 +}
  143.34 +
  143.35 +uint8_t mda_in(uint16_t addr)
  143.36 +{
  143.37 +        switch (addr)
  143.38 +        {
  143.39 +                case 0x3B0: case 0x3B2: case 0x3B4: case 0x3B6:
  143.40 +                return crtcmreg;
  143.41 +                case 0x3B1: case 0x3B3: case 0x3B5: case 0x3B7:
  143.42 +                return crtcm[crtcmreg];
  143.43 +                case 0x3BA:
  143.44 +                return mda_stat | 0xF0;
  143.45 +        }
  143.46 +}
  143.47 +
  143.48 +void mda_write(uint32_t addr, uint8_t val)
  143.49 +{
  143.50 +        vram[addr&0xFFF]=val;
  143.51 +}
  143.52 +
  143.53 +uint8_t mda_read(uint32_t addr)
  143.54 +{
  143.55 +        return vram[addr&0xFFF];
  143.56 +}
  143.57 +
  143.58 +void mda_recalctimings()
  143.59 +{
  143.60 +        disptime=crtc[0]+1;
  143.61 +        dispontime=crtc[1];
  143.62 +        dispofftime=disptime-dispontime;
  143.63 +        dispontime*=MDACONST;
  143.64 +        dispofftime*=MDACONST;
  143.65 +}
  143.66 +
  143.67 +int mdacols[256][2][2];
  143.68 +
  143.69 +static int linepos,displine;
  143.70 +static int vc,sc;
  143.71 +static uint16_t ma,maback,ca;
  143.72 +static int con,coff,cursoron;
  143.73 +static int cgadispon,cgablink;
  143.74 +static int vsynctime,vadj;
  143.75 +
  143.76 +void mda_poll()
  143.77 +{
  143.78 +        uint16_t ca=(crtcm[15]|(crtcm[14]<<8))&0x3FFF;
  143.79 +        int drawcursor;
  143.80 +        int x,c;
  143.81 +        int oldvc;
  143.82 +        uint8_t chr,attr;
  143.83 +        uint16_t dat,dat2,dat3,dat4;
  143.84 +        int cols[4];
  143.85 +        int col;
  143.86 +        int oldsc;
  143.87 +        int blink;
  143.88 +        if (!linepos)
  143.89 +        {
  143.90 +                vidtime+=dispofftime;
  143.91 +                mda_stat|=1;
  143.92 +                linepos=1;
  143.93 +                oldsc=sc;
  143.94 +                if ((crtcm[8]&3)==3) sc=(sc<<1)&7;
  143.95 +                if (cgadispon)
  143.96 +                {
  143.97 +                        if (displine<firstline)
  143.98 +                        {
  143.99 +                                firstline=displine;
 143.100 +                        }
 143.101 +                        lastline=displine;
 143.102 +                        cols[0]=0;
 143.103 +                        cols[1]=7;
 143.104 +                        for (x=0;x<crtcm[1];x++)
 143.105 +                        {
 143.106 +                                chr=vram[(ma<<1)&0x3FFF];
 143.107 +                                attr=vram[((ma<<1)+1)&0x3FFF];
 143.108 +                                drawcursor=((ma==ca) && con && cursoron);
 143.109 +                                blink=((cgablink&16) && (mda_ctrl&0x20) && (attr&0x80) && !drawcursor);
 143.110 +                                if (sc==12 && ((attr&7)==1))
 143.111 +                                {
 143.112 +                                        for (c=0;c<9;c++)
 143.113 +                                            buffer->line[displine][(x*9)+c]=mdacols[attr][blink][1];
 143.114 +                                }
 143.115 +                                else
 143.116 +                                {
 143.117 +                                        for (c=0;c<8;c++)
 143.118 +                                            buffer->line[displine][(x*9)+c]=mdacols[attr][blink][(fontdatm[chr][sc]&(1<<(c^7)))?1:0];
 143.119 +                                        if ((chr&~0x1F)==0xC0) buffer->line[displine][(x*9)+8]=mdacols[attr][blink][fontdatm[chr][sc]&1];
 143.120 +                                        else                   buffer->line[displine][(x*9)+8]=mdacols[attr][blink][0];
 143.121 +                                }
 143.122 +                                ma++;
 143.123 +                                if (drawcursor)
 143.124 +                                {
 143.125 +                                        for (c=0;c<9;c++)
 143.126 +                                            buffer->line[displine][(x*9)+c]^=mdacols[attr][0][1];
 143.127 +                                }
 143.128 +                        }
 143.129 +                }
 143.130 +                sc=oldsc;
 143.131 +                if (vc==crtcm[7] && !sc)
 143.132 +                {
 143.133 +                        mda_stat|=8;
 143.134 +//                        printf("VSYNC on %i %i\n",vc,sc);
 143.135 +                }
 143.136 +                displine++;
 143.137 +                if (displine>=500) displine=0;
 143.138 +        }
 143.139 +        else
 143.140 +        {
 143.141 +                vidtime+=dispontime;
 143.142 +                if (cgadispon) mda_stat&=~1;
 143.143 +                linepos=0;
 143.144 +                if (vsynctime)
 143.145 +                {
 143.146 +                        vsynctime--;
 143.147 +                        if (!vsynctime)
 143.148 +                        {
 143.149 +                                mda_stat&=~8;
 143.150 +//                                printf("VSYNC off %i %i\n",vc,sc);
 143.151 +                        }
 143.152 +                }
 143.153 +                if (sc==(crtcm[11]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[11]&31)>>1))) { con=0; coff=1; }
 143.154 +                if (vadj)
 143.155 +                {
 143.156 +                        sc++;
 143.157 +                        sc&=31;
 143.158 +                        ma=maback;
 143.159 +                        vadj--;
 143.160 +                        if (!vadj)
 143.161 +                        {
 143.162 +                                cgadispon=1;
 143.163 +                                ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
 143.164 +                                sc=0;
 143.165 +                        }
 143.166 +                }
 143.167 +                else if (sc==crtcm[9] || ((crtcm[8]&3)==3 && sc==(crtcm[9]>>1)))
 143.168 +                {
 143.169 +                        maback=ma;
 143.170 +                        sc=0;
 143.171 +                        oldvc=vc;
 143.172 +                        vc++;
 143.173 +                        vc&=127;
 143.174 +                        if (vc==crtcm[6]) cgadispon=0;
 143.175 +                        if (oldvc==crtcm[4])
 143.176 +                        {
 143.177 +//                                printf("Display over at %i\n",displine);
 143.178 +                                vc=0;
 143.179 +                                vadj=crtcm[5];
 143.180 +                                if (!vadj) cgadispon=1;
 143.181 +                                if (!vadj) ma=maback=(crtcm[13]|(crtcm[12]<<8))&0x3FFF;
 143.182 +                                if ((crtcm[10]&0x60)==0x20) cursoron=0;
 143.183 +                                else                        cursoron=cgablink&16;
 143.184 +                        }
 143.185 +                        if (vc==crtcm[7])
 143.186 +                        {
 143.187 +                                cgadispon=0;
 143.188 +                                displine=0;
 143.189 +                                vsynctime=16;//(crtcm[3]>>4)+1;
 143.190 +                                if (crtcm[7])
 143.191 +                                {
 143.192 +//                                        printf("Lastline %i Firstline %i  %i\n",lastline,firstline,lastline-firstline);
 143.193 +                                        x=crtcm[1]*9;
 143.194 +                                        lastline++;
 143.195 +                                        if (x!=xsize || (lastline-firstline)!=ysize)
 143.196 +                                        {
 143.197 +                                                xsize=x;
 143.198 +                                                ysize=lastline-firstline;
 143.199 +//                                                printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
 143.200 +                                                if (xsize<64) xsize=656;
 143.201 +                                                if (ysize<32) ysize=200;
 143.202 +                                                updatewindowsize(xsize,ysize);
 143.203 +                                        }
 143.204 +                                startblit();
 143.205 +                                        video_blit_memtoscreen_8(0, firstline, xsize, lastline - firstline);
 143.206 +                                endblit();
 143.207 +                                        frames++;
 143.208 +                                        video_res_x = crtcm[1];
 143.209 +                                        video_res_y = crtcm[6];
 143.210 +                                        video_bpp = 0;
 143.211 +                                }
 143.212 +                                firstline=1000;
 143.213 +                                lastline=0;
 143.214 +                                cgablink++;
 143.215 +                        }
 143.216 +                }
 143.217 +                else
 143.218 +                {
 143.219 +                        sc++;
 143.220 +                        sc&=31;
 143.221 +                        ma=maback;
 143.222 +                }
 143.223 +                if ((sc==(crtcm[10]&31) || ((crtcm[8]&3)==3 && sc==((crtcm[10]&31)>>1))))
 143.224 +                {
 143.225 +                        con=1;
 143.226 +//                        printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
 143.227 +                }
 143.228 +        }
 143.229 +}
 143.230 +
 143.231 +int mda_init()
 143.232 +{
 143.233 +        mem_sethandler(0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL);
 143.234 +        return 0;
 143.235 +}
 143.236 +
 143.237 +GFXCARD vid_mda =
 143.238 +{
 143.239 +        mda_init,
 143.240 +        /*IO at 3Cx/3Dx*/
 143.241 +        video_out_null,
 143.242 +        video_in_null,
 143.243 +        /*IO at 3Ax/3Bx*/
 143.244 +        mda_out,
 143.245 +        mda_in,
 143.246 +
 143.247 +        mda_poll,
 143.248 +        mda_recalctimings,
 143.249 +
 143.250 +        video_write_null,
 143.251 +        mda_write,
 143.252 +        video_write_null,
 143.253 +
 143.254 +        video_read_null,
 143.255 +        mda_read,
 143.256 +        video_read_null
 143.257 +};
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/src/vid_olivetti_m24.c	Sun Apr 21 14:54:35 2013 +0100
   144.3 @@ -0,0 +1,428 @@
   144.4 +/*Olivetti M24 video emulation
   144.5 +  Essentially double-res CGA*/
   144.6 +#include "ibm.h"
   144.7 +#include "video.h"
   144.8 +
   144.9 +static uint8_t  m24_ctrl;
  144.10 +static uint32_t m24_base;
  144.11 +
  144.12 +void m24_out(uint16_t addr, uint8_t val)
  144.13 +{
  144.14 +        uint8_t old;
  144.15 +        switch (addr)
  144.16 +        {
  144.17 +                case 0x3D4:
  144.18 +                crtcreg = val & 31;
  144.19 +                return;
  144.20 +                case 0x3D5:
  144.21 +                old = crtc[crtcreg];
  144.22 +                crtc[crtcreg] = val & crtcmask[crtcreg];
  144.23 +                if (old != val)
  144.24 +                {
  144.25 +                        if (crtcreg < 0xE || crtcreg > 0x10)
  144.26 +                        {
  144.27 +                                fullchange = changeframecount;
  144.28 +                                m24_recalctimings();
  144.29 +                        }
  144.30 +                }
  144.31 +                return;
  144.32 +                case 0x3D8:
  144.33 +                cgamode = val;
  144.34 +                return;
  144.35 +                case 0x3D9:
  144.36 +                cgacol = val;
  144.37 +                return;
  144.38 +                case 0x3de:
  144.39 +                m24_ctrl = val;
  144.40 +                m24_base = (val & 0x08) ? 0x4000 : 0;
  144.41 +                return;
  144.42 +        }
  144.43 +}
  144.44 +
  144.45 +uint8_t m24_in(uint16_t addr)
  144.46 +{
  144.47 +        switch (addr)
  144.48 +        {
  144.49 +                case 0x3D4:
  144.50 +                return crtcreg;
  144.51 +                case 0x3D5:
  144.52 +                return crtc[crtcreg];
  144.53 +                case 0x3DA:
  144.54 +                return cgastat;
  144.55 +        }
  144.56 +        return 0xFF;
  144.57 +}
  144.58 +
  144.59 +static uint8_t charbuffer[256];
  144.60 +
  144.61 +void m24_write(uint32_t addr, uint8_t val)
  144.62 +{
  144.63 +        vram[addr & 0x7FFF]=val;
  144.64 +        charbuffer[ ((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val;
  144.65 +        charbuffer[(((int)(((dispontime - vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val;        
  144.66 +}
  144.67 +
  144.68 +uint8_t m24_read(uint32_t addr)
  144.69 +{
  144.70 +        return vram[addr & 0x7FFF];
  144.71 +}
  144.72 +
  144.73 +void m24_recalctimings()
  144.74 +{
  144.75 +        if (cgamode & 1)
  144.76 +        {
  144.77 +                disptime   = crtc[0] + 1;
  144.78 +                dispontime = crtc[1];
  144.79 +        }
  144.80 +        else
  144.81 +        {
  144.82 +                disptime   = (crtc[0] + 1) << 1;
  144.83 +                dispontime = crtc[1] << 1;
  144.84 +        }
  144.85 +        dispofftime = disptime - dispontime;
  144.86 +//        printf("%i %f %f %f  %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
  144.87 +        dispontime  *= CGACONST / 2;
  144.88 +        dispofftime *= CGACONST / 2;
  144.89 +//        printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
  144.90 +}
  144.91 +
  144.92 +static int linepos,displine;
  144.93 +static int sc,vc;
  144.94 +static int cgadispon;
  144.95 +static int con,coff,cursoron,cgablink;
  144.96 +static int vsynctime,vadj;
  144.97 +static int m24_lineff = 0;
  144.98 +static uint16_t ma,maback,ca;
  144.99 +
 144.100 +void m24_poll()
 144.101 +{
 144.102 +        uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
 144.103 +        int drawcursor;
 144.104 +        int x,c;
 144.105 +        int oldvc;
 144.106 +        uint8_t chr,attr;
 144.107 +        uint16_t dat,dat2,dat3,dat4;
 144.108 +        int cols[4];
 144.109 +        int col;
 144.110 +        int oldsc;
 144.111 +        if (!linepos)
 144.112 +        {
 144.113 +//                pclog("Line poll  %i %i %i %i - %04X %i %i %i\n", m24_lineff, vc, sc, vadj, ma, firstline, lastline, displine);
 144.114 +                vidtime+=dispofftime;
 144.115 +                cgastat|=1;
 144.116 +                linepos=1;
 144.117 +                oldsc=sc;
 144.118 +                if ((crtc[8]&3)==3) sc=(sc<<1)&7;
 144.119 +                if (cgadispon)
 144.120 +                {
 144.121 +                        if (displine<firstline)
 144.122 +                        {
 144.123 +                                firstline=displine;
 144.124 +//                                printf("Firstline %i\n",firstline);
 144.125 +                        }
 144.126 +                        lastline=displine;
 144.127 +                        for (c=0;c<8;c++)
 144.128 +                        {
 144.129 +                                if ((cgamode&0x12)==0x12)
 144.130 +                                {
 144.131 +                                        buffer->line[displine][c]=0;
 144.132 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
 144.133 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=0;
 144.134 +                                }
 144.135 +                                else
 144.136 +                                {
 144.137 +                                        buffer->line[displine][c]=(cgacol&15)+16;
 144.138 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
 144.139 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
 144.140 +                                }
 144.141 +                        }
 144.142 +                        if (cgamode&1)
 144.143 +                        {
 144.144 +                                for (x=0;x<crtc[1];x++)
 144.145 +                                {
 144.146 +                                        chr  = charbuffer[ x << 1];
 144.147 +                                        attr = charbuffer[(x << 1) + 1];
 144.148 +                                        drawcursor=((ma==ca) && con && cursoron);
 144.149 +                                        if (cgamode&0x20)
 144.150 +                                        {
 144.151 +                                                cols[1]=(attr&15)+16;
 144.152 +                                                cols[0]=((attr>>4)&7)+16;
 144.153 +                                                if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
 144.154 +                                        }
 144.155 +                                        else
 144.156 +                                        {
 144.157 +                                                cols[1]=(attr&15)+16;
 144.158 +                                                cols[0]=(attr>>4)+16;
 144.159 +                                        }
 144.160 +                                        if (drawcursor)
 144.161 +                                        {
 144.162 +                                                for (c=0;c<8;c++)
 144.163 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0]^15;
 144.164 +                                        }
 144.165 +                                        else
 144.166 +                                        {
 144.167 +                                                for (c=0;c<8;c++)
 144.168 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0];
 144.169 +                                        }
 144.170 +                                        ma++;
 144.171 +                                }
 144.172 +                        }
 144.173 +                        else if (!(cgamode&2))
 144.174 +                        {
 144.175 +                                for (x=0;x<crtc[1];x++)
 144.176 +                                {
 144.177 +                                        chr=vram[((ma<<1)&0x3FFF) + m24_base];
 144.178 +                                        attr=vram[(((ma<<1)+1)&0x3FFF) + m24_base];
 144.179 +                                        drawcursor=((ma==ca) && con && cursoron);
 144.180 +                                        if (cgamode&0x20)
 144.181 +                                        {
 144.182 +                                                cols[1]=(attr&15)+16;
 144.183 +                                                cols[0]=((attr>>4)&7)+16;
 144.184 +                                                if ((cgablink&16) && (attr&0x80)) cols[1]=cols[0];
 144.185 +                                        }
 144.186 +                                        else
 144.187 +                                        {
 144.188 +                                                cols[1]=(attr&15)+16;
 144.189 +                                                cols[0]=(attr>>4)+16;
 144.190 +                                        }
 144.191 +                                        ma++;
 144.192 +                                        if (drawcursor)
 144.193 +                                        {
 144.194 +                                                for (c=0;c<8;c++)
 144.195 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0]^15;
 144.196 +                                        }
 144.197 +                                        else
 144.198 +                                        {
 144.199 +                                                for (c=0;c<8;c++)
 144.200 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdatm[chr][((sc & 7) << 1) | m24_lineff]&(1<<(c^7)))?1:0];
 144.201 +                                        }
 144.202 +                                }
 144.203 +                        }
 144.204 +                        else if (!(cgamode&16))
 144.205 +                        {
 144.206 +                                cols[0]=(cgacol&15)|16;
 144.207 +                                col=(cgacol&16)?24:16;
 144.208 +                                if (cgamode&4)
 144.209 +                                {
 144.210 +                                        cols[1]=col|3;
 144.211 +                                        cols[2]=col|4;
 144.212 +                                        cols[3]=col|7;
 144.213 +                                }
 144.214 +                                else if (cgacol&32)
 144.215 +                                {
 144.216 +                                        cols[1]=col|3;
 144.217 +                                        cols[2]=col|5;
 144.218 +                                        cols[3]=col|7;
 144.219 +                                }
 144.220 +                                else
 144.221 +                                {
 144.222 +                                        cols[1]=col|2;
 144.223 +                                        cols[2]=col|4;
 144.224 +                                        cols[3]=col|6;
 144.225 +                                }
 144.226 +                                for (x=0;x<crtc[1];x++)
 144.227 +                                {
 144.228 +                                        dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000) + m24_base]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1 + m24_base];
 144.229 +                                        ma++;
 144.230 +                                        for (c=0;c<8;c++)
 144.231 +                                        {
 144.232 +                                                buffer->line[displine][(x<<4)+(c<<1)+8]=
 144.233 +                                                  buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
 144.234 +                                                dat<<=2;
 144.235 +                                        }
 144.236 +                                }
 144.237 +                        }
 144.238 +                        else
 144.239 +                        {
 144.240 +                                
 144.241 +                                if (m24_ctrl & 1)
 144.242 +                                {                                        
 144.243 +                                        dat2 = ((sc & 1) * 0x4000) | (m24_lineff * 0x2000);
 144.244 +                                        cols[0]=0; cols[1]=/*(cgacol&15)*/15+16;
 144.245 +                                }
 144.246 +                                else
 144.247 +                                {
 144.248 +                                        dat2 =  (sc & 1) * 0x2000;
 144.249 +                                        cols[0]=0; cols[1]=(cgacol&15)+16;
 144.250 +                                }
 144.251 +                                for (x=0;x<crtc[1];x++)
 144.252 +                                {
 144.253 +                                        dat=(vram[((ma<<1)&0x1FFF) + dat2]<<8) | vram[((ma<<1)&0x1FFF) + dat2 + 1];
 144.254 +                                        ma++;
 144.255 +                                        for (c=0;c<16;c++)
 144.256 +                                        {
 144.257 +                                                buffer->line[displine][(x<<4)+c+8]=cols[dat>>15];
 144.258 +                                                dat<<=1;
 144.259 +                                        }
 144.260 +                                }
 144.261 +                        }
 144.262 +                }
 144.263 +                else
 144.264 +                {
 144.265 +                        cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
 144.266 +                        if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
 144.267 +                        else           hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
 144.268 +                }
 144.269 +
 144.270 +                if (cgamode&1) x=(crtc[1]<<3)+16;
 144.271 +                else           x=(crtc[1]<<4)+16;
 144.272 +
 144.273 +                sc=oldsc;
 144.274 +                if (vc==crtc[7] && !sc)
 144.275 +                   cgastat|=8;
 144.276 +                displine++;
 144.277 +                if (displine>=720) displine=0;
 144.278 +        }
 144.279 +        else
 144.280 +        {
 144.281 +//                pclog("Line poll  %i %i %i %i\n", m24_lineff, vc, sc, vadj);
 144.282 +                vidtime+=dispontime;
 144.283 +                if (cgadispon) cgastat&=~1;
 144.284 +                linepos=0;
 144.285 +                m24_lineff ^= 1;
 144.286 +                if (m24_lineff)
 144.287 +                {
 144.288 +                        ma = maback;
 144.289 +                }                
 144.290 +                else
 144.291 +                {
 144.292 +                        if (vsynctime)
 144.293 +                        {
 144.294 +                                vsynctime--;
 144.295 +                                if (!vsynctime)
 144.296 +                                   cgastat&=~8;
 144.297 +                        }
 144.298 +                        if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; }
 144.299 +                        if (vadj)
 144.300 +                        {
 144.301 +                                sc++;
 144.302 +                                sc&=31;
 144.303 +                                ma=maback;
 144.304 +                                vadj--;
 144.305 +                                if (!vadj)
 144.306 +                                {
 144.307 +                                        cgadispon=1;
 144.308 +                                        ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 144.309 +                                        sc=0;
 144.310 +                                }
 144.311 +                        }
 144.312 +                        else if (sc==crtc[9] || ((crtc[8]&3)==3 && sc==(crtc[9]>>1)))
 144.313 +                        {
 144.314 +                                maback=ma;
 144.315 +                                sc=0;
 144.316 +                                oldvc=vc;
 144.317 +                                vc++;
 144.318 +                                vc&=127;
 144.319 +
 144.320 +                                if (vc==crtc[6]) 
 144.321 +                                   cgadispon=0;
 144.322 +                                   
 144.323 +                                if (oldvc==crtc[4])
 144.324 +                                {
 144.325 +                                        vc=0;
 144.326 +                                        vadj=crtc[5];
 144.327 +                                        if (!vadj) cgadispon=1;
 144.328 +                                        if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 144.329 +                                        if ((crtc[10]&0x60)==0x20) cursoron=0;
 144.330 +                                        else                       cursoron=cgablink&16;
 144.331 +                                }
 144.332 +
 144.333 +                                if (vc==crtc[7])
 144.334 +                                {
 144.335 +                                        cgadispon=0;
 144.336 +                                        displine=0;
 144.337 +                                        vsynctime=(crtc[3]>>4)+1;
 144.338 +                                        if (crtc[7])
 144.339 +                                        {
 144.340 +                                                if (cgamode&1) x=(crtc[1]<<3)+16;
 144.341 +                                                else           x=(crtc[1]<<4)+16;
 144.342 +                                                lastline++;
 144.343 +                                                if (x!=xsize || (lastline-firstline)!=ysize)
 144.344 +                                                {
 144.345 +                                                        xsize=x;
 144.346 +                                                        ysize=lastline-firstline;
 144.347 +                                                        if (xsize<64) xsize=656;
 144.348 +                                                        if (ysize<32) ysize=200;
 144.349 +                                                        updatewindowsize(xsize, ysize + 16);
 144.350 +                                                }
 144.351 +startblit();
 144.352 +                                                video_blit_memtoscreen_8(0, firstline - 8, xsize, (lastline - firstline) + 16);
 144.353 +                                                if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
 144.354 +                                                readflash=0;
 144.355 +                                                frames++;
 144.356 +endblit();
 144.357 +                                                video_res_x = xsize - 16;
 144.358 +                                                video_res_y = ysize;
 144.359 +                                                if (cgamode & 1)
 144.360 +                                                {
 144.361 +                                                        video_res_x /= 8;
 144.362 +                                                        video_res_y /= (crtc[9] + 1) * 2;
 144.363 +                                                        video_bpp = 0;
 144.364 +                                                }
 144.365 +                                                else if (!(cgamode & 2))
 144.366 +                                                {
 144.367 +                                                        video_res_x /= 16;
 144.368 +                                                        video_res_y /= (crtc[9] + 1) * 2;
 144.369 +                                                        video_bpp = 0;
 144.370 +                                                }
 144.371 +                                                else if (!(cgamode&16))
 144.372 +                                                {
 144.373 +                                                        video_res_x /= 2;
 144.374 +                                                        video_res_y /= 2;
 144.375 +                                                        video_bpp = 2;
 144.376 +                                                }
 144.377 +                                                else if (!(m24_ctrl & 1))
 144.378 +                                                {
 144.379 +                                                        video_res_y /= 2;
 144.380 +                                                        video_bpp = 1;
 144.381 +                                                }
 144.382 +                                        }
 144.383 +                                        firstline=1000;
 144.384 +                                        lastline=0;
 144.385 +                                        cgablink++;
 144.386 +                                }
 144.387 +                        }
 144.388 +                        else
 144.389 +                        {
 144.390 +                                sc++;
 144.391 +                                sc&=31;
 144.392 +                                ma=maback;
 144.393 +                        }
 144.394 +                        if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1;
 144.395 +                }
 144.396 +                if (cgadispon && (cgamode&1))
 144.397 +                {
 144.398 +                        for (x=0;x<(crtc[1]<<1);x++)
 144.399 +                            charbuffer[x]=vram[(((ma<<1)+x)&0x3FFF) + m24_base];
 144.400 +                }
 144.401 +        }
 144.402 +}
 144.403 +
 144.404 +
 144.405 +int m24_init()
 144.406 +{
 144.407 +        mem_sethandler(0xb8000, 0x08000, m24_read, NULL, NULL, m24_write, NULL, NULL);
 144.408 +        return 0;
 144.409 +}
 144.410 +
 144.411 +GFXCARD vid_m24 =
 144.412 +{
 144.413 +        m24_init,
 144.414 +        /*IO at 3Cx/3Dx*/
 144.415 +        m24_out,
 144.416 +        m24_in,
 144.417 +        /*IO at 3Ax/3Bx*/
 144.418 +        video_out_null,
 144.419 +        video_in_null,
 144.420 +
 144.421 +        m24_poll,
 144.422 +        m24_recalctimings,
 144.423 +
 144.424 +        video_write_null,
 144.425 +        video_write_null,
 144.426 +        m24_write,
 144.427 +
 144.428 +        video_read_null,
 144.429 +        video_read_null,
 144.430 +        m24_read
 144.431 +};
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/src/vid_oti067.c	Sun Apr 21 14:54:35 2013 +0100
   145.3 @@ -0,0 +1,108 @@
   145.4 +/*Oak OTI067 emulation*/
   145.5 +#include "ibm.h"
   145.6 +#include "video.h"
   145.7 +#include "vid_svga.h"
   145.8 +
   145.9 +static int oti067_index;
  145.10 +static uint8_t oti067_regs[32];
  145.11 +
  145.12 +void oti067_out(uint16_t addr, uint8_t val)
  145.13 +{
  145.14 +        uint8_t old;
  145.15 +        
  145.16 +        if ((addr&0xFFF0) == 0x3B0) addr |= 0x20;
  145.17 +
  145.18 +        switch (addr)
  145.19 +        {
  145.20 +                case 0x3D4:
  145.21 +                crtcreg=val&31;
  145.22 +                return;
  145.23 +                case 0x3D5:
  145.24 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
  145.25 +                old=crtc[crtcreg];
  145.26 +                crtc[crtcreg]=val;
  145.27 +                if (old!=val)
  145.28 +                {
  145.29 +                        if (crtcreg<0xE || crtcreg>0x10)
  145.30 +                        {
  145.31 +                                fullchange=changeframecount;
  145.32 +                                svga_recalctimings();
  145.33 +                        }
  145.34 +                }
  145.35 +                break;
  145.36 +
  145.37 +                case 0x3DE: oti067_index=val&0x1F; return;
  145.38 +                case 0x3DF:
  145.39 +                oti067_regs[oti067_index]=val;
  145.40 +                switch (oti067_index)
  145.41 +                {
  145.42 +                        case 0xD:
  145.43 +                        vrammask=(val&0xC)?0x7FFFF:0x3FFFF;
  145.44 +                        break;
  145.45 +                        case 0x11:
  145.46 +                        svgarbank=(val&0xF)*65536;
  145.47 +                        svgawbank=(val>>4)*65536;
  145.48 +                        break;
  145.49 +                }
  145.50 +                return;
  145.51 +        }
  145.52 +        svga_out(addr,val);
  145.53 +}
  145.54 +
  145.55 +uint8_t oti067_in(uint16_t addr)
  145.56 +{
  145.57 +        uint8_t temp;
  145.58 +        
  145.59 +        if ((addr&0xFFF0) == 0x3B0) addr |= 0x20;
  145.60 +        
  145.61 +        switch (addr)
  145.62 +        {
  145.63 +                case 0x3D4:
  145.64 +                return crtcreg;
  145.65 +                case 0x3D5:
  145.66 +                return crtc[crtcreg];
  145.67 +                case 0x3DE: return oti067_index|(2<<5);
  145.68 +                case 0x3DF: 
  145.69 +                if (oti067_index==0x10) return 0x40;
  145.70 +                if (oti067_index==0xD) return oti067_regs[oti067_index]|0xC0;
  145.71 +                return oti067_regs[oti067_index];
  145.72 +        }
  145.73 +        return svga_in(addr);
  145.74 +}
  145.75 +
  145.76 +void oti067_recalctimings()
  145.77 +{
  145.78 +        if (oti067_regs[0x14]&0x08) svga_ma|=0x10000;
  145.79 +        if (oti067_regs[0x0D]&0x0C) svga_rowoffset<<=1;
  145.80 +        svga_interlace = oti067_regs[0x14]&0x80;
  145.81 +}
  145.82 +
  145.83 +int oti067_init()
  145.84 +{
  145.85 +        svga_recalctimings_ex = oti067_recalctimings;
  145.86 +        svga_vram_limit = 1 << 19; /*512kb*/
  145.87 +        vrammask = 0x7ffff;
  145.88 +        return svga_init();
  145.89 +}
  145.90 +
  145.91 +GFXCARD vid_oti067 =
  145.92 +{
  145.93 +        oti067_init,
  145.94 +        /*IO at 3Cx/3Dx*/
  145.95 +        oti067_out,
  145.96 +        oti067_in,
  145.97 +        /*IO at 3Ax/3Bx*/
  145.98 +        video_out_null,
  145.99 +        video_in_null,
 145.100 +
 145.101 +        svga_poll,
 145.102 +        svga_recalctimings,
 145.103 +
 145.104 +        svga_write,
 145.105 +        video_write_null,
 145.106 +        video_write_null,
 145.107 +
 145.108 +        svga_read,
 145.109 +        video_read_null,
 145.110 +        video_read_null
 145.111 +};
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/src/vid_paradise.c	Sun Apr 21 14:54:35 2013 +0100
   146.3 @@ -0,0 +1,273 @@
   146.4 +/*Paradise VGA emulation
   146.5 +
   146.6 +  PC2086, PC3086 use PVGA1A
   146.7 +  MegaPC uses W90C11A
   146.8 +  */
   146.9 +#include "ibm.h"
  146.10 +#include "video.h"
  146.11 +#include "vid_svga.h"
  146.12 +#include "vid_unk_ramdac.h"
  146.13 +
  146.14 +void    paradise_write(uint32_t addr, uint8_t val);
  146.15 +uint8_t paradise_read(uint32_t addr);
  146.16 +
  146.17 +enum
  146.18 +{
  146.19 +        PVGA1A = 0,
  146.20 +        WD90C11
  146.21 +};
  146.22 +
  146.23 +static int paradise_type;
  146.24 +
  146.25 +static uint32_t paradise_bank_r[4], paradise_bank_w[4];
  146.26 +
  146.27 +void paradise_out(uint16_t addr, uint8_t val)
  146.28 +{
  146.29 +        uint8_t old;
  146.30 +        
  146.31 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  146.32 +//        output = 3;
  146.33 +        pclog("Paradise out %04X %02X %04X:%04X\n", addr, val, CS, pc);
  146.34 +        switch (addr)
  146.35 +        {
  146.36 +                case 0x3c5:
  146.37 +                if (seqaddr > 7)                        
  146.38 +                {
  146.39 +                        if (paradise_type < WD90C11 || seqregs[6] != 0x48) 
  146.40 +                           return;
  146.41 +                        seqregs[seqaddr & 0x1f] = val;
  146.42 +                        if (seqaddr == 0x11)
  146.43 +                           paradise_remap();
  146.44 +                        return;
  146.45 +                }
  146.46 +                break;
  146.47 +
  146.48 +                case 0x3cf:
  146.49 +                if (gdcaddr >= 0x9 && gdcaddr < 0xf)
  146.50 +                {
  146.51 +                        if ((gdcreg[0xf] & 7) != 5)
  146.52 +                           return;
  146.53 +                }
  146.54 +                if (gdcaddr == 6)
  146.55 +                {
  146.56 +                        if ((gdcreg[6] & 0xc) != (val & 0xc))
  146.57 +                        {
  146.58 +                                mem_removehandler(0xa0000, 0x20000, paradise_read, NULL, NULL, svga_write, NULL, NULL);
  146.59 +//                                pclog("Write mapping %02X\n", val);
  146.60 +                                switch (val&0xC)
  146.61 +                                {
  146.62 +                                        case 0x0: /*128k at A0000*/
  146.63 +                                        mem_sethandler(0xa0000, 0x20000, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
  146.64 +                                        break;
  146.65 +                                        case 0x4: /*64k at A0000*/
  146.66 +                                        mem_sethandler(0xa0000, 0x10000, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
  146.67 +                                        break;
  146.68 +                                        case 0x8: /*32k at B0000*/
  146.69 +                                        mem_sethandler(0xb0000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
  146.70 +                                        break;
  146.71 +                                        case 0xC: /*32k at B8000*/
  146.72 +                                        mem_sethandler(0xb8000, 0x08000, paradise_read, NULL, NULL, paradise_write, NULL, NULL);
  146.73 +                                        break;
  146.74 +                                }
  146.75 +                        }
  146.76 +                        gdcreg[6] = val;
  146.77 +                        paradise_remap();
  146.78 +                        return;
  146.79 +                }
  146.80 +                if (gdcaddr == 0x9 || gdcaddr == 0xa)
  146.81 +                {
  146.82 +                        gdcreg[gdcaddr] = val;
  146.83 +                        paradise_remap();
  146.84 +                        return;
  146.85 +                }
  146.86 +                if (gdcaddr == 0xe)
  146.87 +                {
  146.88 +                        gdcreg[0xe] = val;
  146.89 +                        paradise_remap();
  146.90 +                        return;
  146.91 +                }
  146.92 +                break;
  146.93 +                
  146.94 +                case 0x3D4:
  146.95 +                if (paradise_type == PVGA1A)
  146.96 +                   crtcreg = val & 0x1f;
  146.97 +                else
  146.98 +                   crtcreg = val & 0x3f;
  146.99 +                return;
 146.100 +                case 0x3D5:
 146.101 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) 
 146.102 +                   return;
 146.103 +                if (crtcreg > 0x29 && (crtc[0x29] & 7) != 5)
 146.104 +                   return;
 146.105 +                if (crtcreg >= 0x31 && crtcreg <= 0x37)
 146.106 +                   return;
 146.107 +                old=crtc[crtcreg];
 146.108 +                crtc[crtcreg]=val;
 146.109 +
 146.110 +                if (old!=val)
 146.111 +                {
 146.112 +                        if (crtcreg<0xE || crtcreg>0x10)
 146.113 +                        {
 146.114 +                                fullchange=changeframecount;
 146.115 +                                svga_recalctimings();
 146.116 +                        }
 146.117 +                }
 146.118 +                break;
 146.119 +        }
 146.120 +        svga_out(addr,val);
 146.121 +}
 146.122 +
 146.123 +uint8_t paradise_in(uint16_t addr)
 146.124 +{
 146.125 +        uint8_t temp;
 146.126 +        
 146.127 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
 146.128 +        
 146.129 +//        if (addr != 0x3da) pclog("Paradise in %04X\n", addr);
 146.130 +        switch (addr)
 146.131 +        {
 146.132 +                case 0x3c5:
 146.133 +                if (seqaddr > 7)
 146.134 +                {
 146.135 +                        if (paradise_type < WD90C11 || seqregs[6] != 0x48) 
 146.136 +                           return 0xff;
 146.137 +                        if (seqaddr > 0x12) 
 146.138 +                           return 0xff;
 146.139 +                        return seqregs[seqaddr & 0x1f];
 146.140 +                }
 146.141 +                break;
 146.142 +                        
 146.143 +                case 0x3cf:
 146.144 +                if (gdcaddr >= 0x9 && gdcaddr < 0xf)
 146.145 +                {
 146.146 +                        if (gdcreg[0xf] & 0x10)
 146.147 +                           return 0xff;
 146.148 +                        switch (gdcaddr)
 146.149 +                        {
 146.150 +                                case 0xf:
 146.151 +                                return (gdcreg[0xf] & 0x17) | 0x80;
 146.152 +                        }
 146.153 +                }
 146.154 +                break;
 146.155 +
 146.156 +                case 0x3D4:
 146.157 +                return crtcreg;
 146.158 +                case 0x3D5:
 146.159 +                if (crtcreg > 0x29 && crtcreg < 0x30 && (crtc[0x29] & 0x88) != 0x80)
 146.160 +                   return 0xff;
 146.161 +                return crtc[crtcreg];
 146.162 +        }
 146.163 +        return svga_in(addr);
 146.164 +}
 146.165 +
 146.166 +void paradise_remap()
 146.167 +{
 146.168 +        if (seqregs[0x11] & 0x80)
 146.169 +        {
 146.170 +//                pclog("Remap 1\n");
 146.171 +                paradise_bank_r[0] = paradise_bank_r[2] =  (gdcreg[0x9] & 0x7f) << 12;
 146.172 +                paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.173 +                paradise_bank_w[0] = paradise_bank_w[2] =  (gdcreg[0xa] & 0x7f) << 12;
 146.174 +                paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.175 +        }
 146.176 +        else if (gdcreg[0xe] & 0x08)
 146.177 +        {
 146.178 +                if (gdcreg[0x6] & 0xc)
 146.179 +                {
 146.180 +//                pclog("Remap 2\n");                        
 146.181 +                        paradise_bank_r[0] = paradise_bank_r[2] =  (gdcreg[0xa] & 0x7f) << 12;
 146.182 +                        paradise_bank_w[0] = paradise_bank_w[2] =  (gdcreg[0xa] & 0x7f) << 12;
 146.183 +                        paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.184 +                        paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.185 +                }
 146.186 +                else
 146.187 +                {
 146.188 +//                pclog("Remap 3\n");
 146.189 +                        paradise_bank_r[0] = paradise_bank_w[0] =  (gdcreg[0xa] & 0x7f) << 12;
 146.190 +                        paradise_bank_r[1] = paradise_bank_w[1] = ((gdcreg[0xa] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.191 +                        paradise_bank_w[2] = paradise_bank_w[2] =  (gdcreg[0x9] & 0x7f) << 12;
 146.192 +                        paradise_bank_w[3] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.193 +                }
 146.194 +        }
 146.195 +        else
 146.196 +        {
 146.197 +  //              pclog("Remap 4\n");
 146.198 +                paradise_bank_r[0] = paradise_bank_r[2] =  (gdcreg[0x9] & 0x7f) << 12;
 146.199 +                paradise_bank_r[1] = paradise_bank_r[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.200 +                paradise_bank_w[0] = paradise_bank_w[2] =  (gdcreg[0x9] & 0x7f) << 12;
 146.201 +                paradise_bank_w[1] = paradise_bank_w[3] = ((gdcreg[0x9] & 0x7f) << 12) + ((gdcreg[6] & 0x08) ? 0 : 0x8000);
 146.202 +        }
 146.203 +//        pclog("Remap - %04X %04X\n", paradise_bank_r[0], paradise_bank_w[0]);
 146.204 +}
 146.205 +
 146.206 +void paradise_recalctimings()
 146.207 +{
 146.208 +        svga_lowres = !(gdcreg[0xe] & 0x01);
 146.209 +}
 146.210 +
 146.211 +#define egacycles 1
 146.212 +#define egacycles2 1
 146.213 +void paradise_write(uint32_t addr, uint8_t val)
 146.214 +{
 146.215 +//        pclog("paradise_write : %05X %02X  ", addr, val);
 146.216 +        addr = (addr & 0x7fff) + paradise_bank_w[(addr >> 15) & 3];
 146.217 +//        pclog("%08X\n", addr);
 146.218 +        svga_write_linear(addr, val);
 146.219 +}
 146.220 +
 146.221 +uint8_t paradise_read(uint32_t addr)
 146.222 +{
 146.223 +//        pclog("paradise_read : %05X ", addr);
 146.224 +        addr = (addr & 0x7fff) + paradise_bank_r[(addr >> 15) & 3];
 146.225 +//        pclog("%08X\n", addr);
 146.226 +        return svga_read_linear(addr);
 146.227 +}
 146.228 +
 146.229 +int paradise_init()
 146.230 +{
 146.231 +        if (romset == ROM_PC2086 || romset == ROM_PC3086)
 146.232 +        {
 146.233 +                paradise_type = PVGA1A;               
 146.234 +                vrammask = 0x3ffff;
 146.235 +                pclog("Init PVGA1A\n");
 146.236 +                svga_vram_limit = 1 << 18; /*256kb*/
 146.237 +        }
 146.238 +        if (romset == ROM_MEGAPC)
 146.239 +        {
 146.240 +                paradise_type = WD90C11;
 146.241 +                vrammask = 0x7ffff;
 146.242 +                crtc[0x36] = '1';
 146.243 +                crtc[0x37] = '1';
 146.244 +                pclog("Init WD90C11\n");
 146.245 +                svga_vram_limit = 1 << 19; /*512kb*/
 146.246 +        }
 146.247 +        crtc[0x31] = 'W';
 146.248 +        crtc[0x32] = 'D';
 146.249 +        crtc[0x33] = '9';
 146.250 +        crtc[0x34] = '0';
 146.251 +        crtc[0x35] = 'C';                                
 146.252 +        svga_recalctimings_ex = paradise_recalctimings;
 146.253 +        return svga_init();
 146.254 +}
 146.255 +
 146.256 +GFXCARD vid_paradise =
 146.257 +{
 146.258 +        paradise_init,
 146.259 +        /*IO at 3Cx/3Dx*/
 146.260 +        paradise_out,
 146.261 +        paradise_in,
 146.262 +        /*IO at 3Ax/3Bx*/
 146.263 +        video_out_null,
 146.264 +        video_in_null,
 146.265 +
 146.266 +        svga_poll,
 146.267 +        svga_recalctimings,
 146.268 +
 146.269 +        paradise_write,
 146.270 +        video_write_null,
 146.271 +        video_write_null,
 146.272 +
 146.273 +        paradise_read,
 146.274 +        video_read_null,
 146.275 +        video_read_null
 146.276 +};
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/src/vid_pc1512.c	Sun Apr 21 14:54:35 2013 +0100
   147.3 @@ -0,0 +1,444 @@
   147.4 +/*PC1512 CGA emulation
   147.5 +
   147.6 +  The PC1512 extends CGA with a bit-planar 640x200x16 mode.
   147.7 +  
   147.8 +  Most CRTC registers are fixed.
   147.9 +  
  147.10 +  The Technical Reference Manual lists the video waitstate time as between 12 
  147.11 +  and 46 cycles. PCem currently always uses the lower number.*/
  147.12 +
  147.13 +#include "ibm.h"
  147.14 +#include "video.h"
  147.15 +#include "vid_cga.h"
  147.16 +
  147.17 +static uint8_t pc1512_plane_write,pc1512_plane_read,pc1512_border;
  147.18 +
  147.19 +void pc1512_recalctimings();
  147.20 +
  147.21 +void pc1512_out(uint16_t addr, uint8_t val)
  147.22 +{
  147.23 +        uint8_t old;
  147.24 +//        pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc);
  147.25 +        switch (addr)
  147.26 +        {
  147.27 +                case 0x3D4:
  147.28 +                crtcreg=val&31;
  147.29 +                return;
  147.30 +                case 0x3D5:
  147.31 +                old=crtc[crtcreg];
  147.32 +                crtc[crtcreg]=val&crtcmask[crtcreg];
  147.33 +                if (old!=val)
  147.34 +                {
  147.35 +                        if (crtcreg<0xE || crtcreg>0x10)
  147.36 +                        {
  147.37 +                                fullchange=changeframecount;
  147.38 +                                pc1512_recalctimings();
  147.39 +                        }
  147.40 +                }
  147.41 +                return;
  147.42 +                case 0x3D8:
  147.43 +                if ((val&0x12)==0x12 && (cgamode&0x12)!=0x12)
  147.44 +                {
  147.45 +                        pc1512_plane_write=0xF;
  147.46 +                        pc1512_plane_read =0;
  147.47 +                }
  147.48 +                cgamode=val;
  147.49 +                return;
  147.50 +                case 0x3D9:
  147.51 +                cgacol=val;
  147.52 +                return;
  147.53 +                case 0x3DD:
  147.54 +                pc1512_plane_write=val;
  147.55 +                return;
  147.56 +                case 0x3DE:
  147.57 +                pc1512_plane_read=val&3;
  147.58 +                return;
  147.59 +                case 0x3DF:
  147.60 +                pc1512_border=val;
  147.61 +                return;
  147.62 +        }
  147.63 +}
  147.64 +
  147.65 +uint8_t pc1512_in(uint16_t addr)
  147.66 +{
  147.67 +//        pclog("PC1512 in %04X %02X %04X:%04X\n",addr,CS,pc);
  147.68 +        switch (addr)
  147.69 +        {
  147.70 +                case 0x3D4:
  147.71 +                return crtcreg;
  147.72 +                case 0x3D5:
  147.73 +                return crtc[crtcreg];
  147.74 +                case 0x3DA:
  147.75 +                return cgastat;
  147.76 +        }
  147.77 +        return 0xFF;
  147.78 +}
  147.79 +
  147.80 +void pc1512_write(uint32_t addr, uint8_t val)
  147.81 +{
  147.82 +/*        if (CS==0x023E && pc==0x524E)
  147.83 +        {
  147.84 +                dumpregs();
  147.85 +                exit(-1);
  147.86 +        }
  147.87 +       pclog("PC1512 write %08X %02X %02X %01X  %04X:%04X\n",addr,val,cgamode&0x12,pc1512_plane_write,CS,pc);*/
  147.88 +        cycles-=12;
  147.89 +        addr&=0x7FFF;
  147.90 +        if ((cgamode&0x12)==0x12)
  147.91 +        {
  147.92 +                if (pc1512_plane_write&1) vram[addr]=val;
  147.93 +                if (pc1512_plane_write&2) vram[addr|0x10000]=val;
  147.94 +                if (pc1512_plane_write&4) vram[addr|0x20000]=val;
  147.95 +                if (pc1512_plane_write&8) vram[addr|0x30000]=val;
  147.96 +        }
  147.97 +        else
  147.98 +           vram[addr]=val;
  147.99 +}
 147.100 +
 147.101 +uint8_t pc1512_read(uint32_t addr)
 147.102 +{
 147.103 +//        pclog("PC1512 read %08X %02X %01X\n",addr,cgamode&0x12,pc1512_plane_read);
 147.104 +        cycles-=12;
 147.105 +        addr&=0x7FFF;
 147.106 +        if ((cgamode&0x12)==0x12)
 147.107 +           return vram[addr|(pc1512_plane_read<<16)];
 147.108 +        return vram[addr];
 147.109 +}
 147.110 +
 147.111 +
 147.112 +static int linepos,displine;
 147.113 +static int sc,vc;
 147.114 +static int cgadispon;
 147.115 +static int con,coff,cursoron,cgablink;
 147.116 +static int vsynctime,vadj;
 147.117 +static uint16_t ma,maback,ca;
 147.118 +
 147.119 +static int ntsc_col[8][8]=
 147.120 +{
 147.121 +        {0,0,0,0,0,0,0,0}, /*Black*/
 147.122 +        {0,0,1,1,1,1,0,0}, /*Blue*/
 147.123 +        {1,0,0,0,0,1,1,1}, /*Green*/
 147.124 +        {0,0,0,0,1,1,1,1}, /*Cyan*/
 147.125 +        {1,1,1,1,0,0,0,0}, /*Red*/
 147.126 +        {0,1,1,1,1,0,0,0}, /*Magenta*/
 147.127 +        {1,1,0,0,0,0,1,1}, /*Yellow*/
 147.128 +        {1,1,1,1,1,1,1,1}  /*White*/
 147.129 +};
 147.130 +
 147.131 +int i_filt[8],q_filt[8];
 147.132 +
 147.133 +
 147.134 +void pc1512_recalctimings()
 147.135 +{
 147.136 +        disptime = 128; /*Fixed on PC1512*/
 147.137 +        dispontime = 80;
 147.138 +        dispofftime=disptime-dispontime;
 147.139 +//        printf("%i %f %f %f  %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
 147.140 +        dispontime*=CGACONST;
 147.141 +        dispofftime*=CGACONST;
 147.142 +//        printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
 147.143 +}
 147.144 +
 147.145 +void pc1512_poll()
 147.146 +{
 147.147 +        uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
 147.148 +        int drawcursor;
 147.149 +        int x,c;
 147.150 +        int oldvc;
 147.151 +        uint8_t chr,attr;
 147.152 +        uint16_t dat,dat2,dat3,dat4;
 147.153 +        int cols[4];
 147.154 +        int col;
 147.155 +        int oldsc;
 147.156 +
 147.157 +        if (!linepos)
 147.158 +        {
 147.159 +                vidtime+=dispofftime;
 147.160 +                cgastat|=1;
 147.161 +                linepos=1;
 147.162 +                oldsc=sc;
 147.163 +                if (cgadispon)
 147.164 +                {
 147.165 +                        if (displine<firstline) firstline=displine;
 147.166 +                        lastline=displine;
 147.167 +                        for (c=0;c<8;c++)
 147.168 +                        {
 147.169 +                                if ((cgamode&0x12)==0x12)
 147.170 +                                {
 147.171 +                                        buffer->line[displine][c]=(pc1512_border&15)+16;
 147.172 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
 147.173 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=0;
 147.174 +                                }
 147.175 +                                else
 147.176 +                                {
 147.177 +                                        buffer->line[displine][c]=(cgacol&15)+16;
 147.178 +                                        if (cgamode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(cgacol&15)+16;
 147.179 +                                        else           buffer->line[displine][c+(crtc[1]<<4)+8]=(cgacol&15)+16;
 147.180 +                                }
 147.181 +                        }
 147.182 +                        if (cgamode&1)
 147.183 +                        {
 147.184 +                                for (x = 0; x < 80; x++)
 147.185 +                                {
 147.186 +                                        chr=vram[((ma<<1)&0x3FFF)];
 147.187 +                                        attr=vram[(((ma<<1)+1)&0x3FFF)];
 147.188 +                                        drawcursor=((ma==ca) && con && cursoron);
 147.189 +                                        if (cgamode&0x20)
 147.190 +                                        {
 147.191 +                                                cols[1]=(attr&15)+16;
 147.192 +                                                cols[0]=((attr>>4)&7)+16;
 147.193 +                                                if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
 147.194 +                                        }
 147.195 +                                        else
 147.196 +                                        {
 147.197 +                                                cols[1]=(attr&15)+16;
 147.198 +                                                cols[0]=(attr>>4)+16;
 147.199 +                                        }
 147.200 +                                        if (drawcursor)
 147.201 +                                        {
 147.202 +                                                for (c=0;c<8;c++)
 147.203 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
 147.204 +                                        }
 147.205 +                                        else
 147.206 +                                        {
 147.207 +                                                for (c=0;c<8;c++)
 147.208 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 147.209 +                                        }
 147.210 +                                        ma++;
 147.211 +                                }
 147.212 +                        }
 147.213 +                        else if (!(cgamode&2))
 147.214 +                        {
 147.215 +                                for (x = 0; x < 40; x++)
 147.216 +                                {
 147.217 +                                        chr=vram[((ma<<1)&0x3FFF)];
 147.218 +                                        attr=vram[(((ma<<1)+1)&0x3FFF)];
 147.219 +                                        drawcursor=((ma==ca) && con && cursoron);
 147.220 +                                        if (cgamode&0x20)
 147.221 +                                        {
 147.222 +                                                cols[1]=(attr&15)+16;
 147.223 +                                                cols[0]=((attr>>4)&7)+16;
 147.224 +                                                if ((cgablink&16) && (attr&0x80)) cols[1]=cols[0];
 147.225 +                                        }
 147.226 +                                        else
 147.227 +                                        {
 147.228 +                                                cols[1]=(attr&15)+16;
 147.229 +                                                cols[0]=(attr>>4)+16;
 147.230 +                                        }
 147.231 +                                        ma++;
 147.232 +                                        if (drawcursor)
 147.233 +                                        {
 147.234 +                                                for (c=0;c<8;c++)
 147.235 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0]^15;
 147.236 +                                        }
 147.237 +                                        else
 147.238 +                                        {
 147.239 +                                                for (c=0;c<8;c++)
 147.240 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 147.241 +                                        }
 147.242 +                                }
 147.243 +                        }
 147.244 +                        else if (!(cgamode&16))
 147.245 +                        {
 147.246 +                                cols[0]=(cgacol&15)|16;
 147.247 +                                col=(cgacol&16)?24:16;
 147.248 +                                if (cgamode&4)
 147.249 +                                {
 147.250 +                                        cols[1]=col|3;
 147.251 +                                        cols[2]=col|4;
 147.252 +                                        cols[3]=col|7;
 147.253 +                                }
 147.254 +                                else if (cgacol&32)
 147.255 +                                {
 147.256 +                                        cols[1]=col|3;
 147.257 +                                        cols[2]=col|5;
 147.258 +                                        cols[3]=col|7;
 147.259 +                                }
 147.260 +                                else
 147.261 +                                {
 147.262 +                                        cols[1]=col|2;
 147.263 +                                        cols[2]=col|4;
 147.264 +                                        cols[3]=col|6;
 147.265 +                                }
 147.266 +                                for (x = 0; x < 40; x++)
 147.267 +                                {
 147.268 +                                        dat=(vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
 147.269 +                                        ma++;
 147.270 +                                        for (c=0;c<8;c++)
 147.271 +                                        {
 147.272 +                                                buffer->line[displine][(x<<4)+(c<<1)+8]=
 147.273 +                                                  buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
 147.274 +                                                dat<<=2;
 147.275 +                                        }
 147.276 +                                }
 147.277 +                        }
 147.278 +                        else
 147.279 +                        {
 147.280 +                                for (x = 0; x < 40; x++)
 147.281 +                                {
 147.282 +                                        ca=((ma<<1)&0x1FFF)+((sc&1)*0x2000);
 147.283 +                                        dat=(vram[ca]<<8)|vram[ca+1];
 147.284 +                                        dat2=(vram[ca+0x10000]<<8)|vram[ca+0x10001];
 147.285 +                                        dat3=(vram[ca+0x20000]<<8)|vram[ca+0x20001];
 147.286 +                                        dat4=(vram[ca+0x30000]<<8)|vram[ca+0x30001];
 147.287 +
 147.288 +                                        ma++;
 147.289 +                                        for (c=0;c<16;c++)
 147.290 +                                        {
 147.291 +                                                buffer->line[displine][(x<<4)+c+8]=(((dat>>15)|((dat2>>15)<<1)|((dat3>>15)<<2)|((dat4>>15)<<3))&(cgacol&15))+16;
 147.292 +                                                dat<<=1;
 147.293 +                                                dat2<<=1;
 147.294 +                                                dat3<<=1;
 147.295 +                                                dat4<<=1;
 147.296 +                                        }
 147.297 +                                }
 147.298 +                        }
 147.299 +                }
 147.300 +                else
 147.301 +                {
 147.302 +                        cols[0]=((cgamode&0x12)==0x12)?0:(cgacol&15)+16;
 147.303 +                        if (cgamode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
 147.304 +                        else           hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
 147.305 +                }
 147.306 +
 147.307 +                sc=oldsc;
 147.308 +                if (vsynctime)
 147.309 +                   cgastat|=8;
 147.310 +                displine++;
 147.311 +                if (displine>=360) displine=0;
 147.312 +//                pclog("Line %i %i %i %i  %i %i\n",displine,cgadispon,firstline,lastline,vc,sc);
 147.313 +        }
 147.314 +        else
 147.315 +        {
 147.316 +                vidtime+=dispontime;
 147.317 +                if ((lastline-firstline)==199) cgadispon=0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
 147.318 +                if (cgadispon) cgastat&=~1;
 147.319 +                linepos=0;
 147.320 +                if (vsynctime)
 147.321 +                {
 147.322 +                        vsynctime--;
 147.323 +                        if (!vsynctime)
 147.324 +                           cgastat&=~8;
 147.325 +                }
 147.326 +                if (sc==(crtc[11]&31)) { con=0; coff=1; }
 147.327 +                if (vadj)
 147.328 +                {
 147.329 +                        sc++;
 147.330 +                        sc&=31;
 147.331 +                        ma=maback;
 147.332 +                        vadj--;
 147.333 +                        if (!vadj)
 147.334 +                        {
 147.335 +                                cgadispon=1;
 147.336 +                                ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 147.337 +                                sc=0;
 147.338 +                        }
 147.339 +                }
 147.340 +                else if (sc==crtc[9])
 147.341 +                {
 147.342 +                        maback=ma;
 147.343 +                        sc=0;
 147.344 +                        oldvc=vc;
 147.345 +                        vc++;
 147.346 +                        vc&=127;
 147.347 +
 147.348 +                        if (displine == 32)//oldvc == (cgamode & 2) ? 127 : 31)
 147.349 +                        {
 147.350 +                                vc=0;
 147.351 +                                vadj=6;
 147.352 +                                if ((crtc[10]&0x60)==0x20) cursoron=0;
 147.353 +                                else                       cursoron=cgablink&16;
 147.354 +                        }
 147.355 +
 147.356 +                        if (displine >= 262)//vc == (cgamode & 2) ? 111 : 27)
 147.357 +                        {
 147.358 +                                cgadispon=0;
 147.359 +                                displine=0;
 147.360 +                                vsynctime=46;
 147.361 +
 147.362 +                                        if (cgamode&1) x=(crtc[1]<<3)+16;
 147.363 +                                        else           x=(crtc[1]<<4)+16;
 147.364 +                                        x = 640 + 16;
 147.365 +                                        lastline++;
 147.366 +                                        if (x!=xsize || (lastline-firstline)!=ysize)
 147.367 +                                        {
 147.368 +                                                xsize=x;
 147.369 +                                                ysize=lastline-firstline;
 147.370 +                                                if (xsize<64) xsize=656;
 147.371 +                                                if (ysize<32) ysize=200;
 147.372 +                                                updatewindowsize(xsize,(ysize<<1)+16);
 147.373 +                                        }
 147.374 +startblit();
 147.375 +                                        video_blit_memtoscreen_8(0, firstline - 4, xsize, (lastline - firstline) + 8);
 147.376 +//                                        blit(buffer,vbuf,0,firstline-4,0,0,xsize,(lastline-firstline)+8+1);
 147.377 +//                                        if (vid_resize) stretch_blit(vbuf,screen,0,0,xsize,(lastline-firstline)+8+1,0,0,winsizex,winsizey);
 147.378 +//                                        else            stretch_blit(vbuf,screen,0,0,xsize,(lastline-firstline)+8+1,0,0,xsize,((lastline-firstline)<<1)+16+2);
 147.379 +//                                        if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
 147.380 +//                                        readflash=0;
 147.381 +endblit();
 147.382 +                                        video_res_x = xsize - 16;
 147.383 +                                        video_res_y = ysize;
 147.384 +                                        if (cgamode & 1)
 147.385 +                                        {
 147.386 +                                                video_res_x /= 8;
 147.387 +                                                video_res_y /= crtc[9] + 1;
 147.388 +                                                video_bpp = 0;
 147.389 +                                        }
 147.390 +                                        else if (!(cgamode & 2))
 147.391 +                                        {
 147.392 +                                                video_res_x /= 16;
 147.393 +                                                video_res_y /= crtc[9] + 1;
 147.394 +                                                video_bpp = 0;
 147.395 +                                        }
 147.396 +                                        else if (!(cgamode&16))
 147.397 +                                        {
 147.398 +                                                video_res_x /= 2;
 147.399 +                                                video_bpp = 2;
 147.400 +                                        }
 147.401 +                                        else
 147.402 +                                        {
 147.403 +                                                video_bpp = 4;
 147.404 +                                        }
 147.405 +
 147.406 +                                firstline=1000;
 147.407 +                                lastline=0;
 147.408 +                                cgablink++;
 147.409 +                        }
 147.410 +                }
 147.411 +                else
 147.412 +                {
 147.413 +                        sc++;
 147.414 +                        sc&=31;
 147.415 +                        ma=maback;
 147.416 +                }
 147.417 +                if (sc==(crtc[10]&31)) con=1;
 147.418 +        }
 147.419 +}
 147.420 +
 147.421 +int pc1512_init()
 147.422 +{
 147.423 +        mem_sethandler(0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL);
 147.424 +        return 0;
 147.425 +}
 147.426 +
 147.427 +GFXCARD vid_pc1512 =
 147.428 +{
 147.429 +        pc1512_init,
 147.430 +        /*IO at 3Cx/3Dx*/
 147.431 +        pc1512_out,
 147.432 +        pc1512_in,
 147.433 +        /*IO at 3Ax/3Bx*/
 147.434 +        video_out_null,
 147.435 +        video_in_null,
 147.436 +
 147.437 +        pc1512_poll,
 147.438 +        pc1512_recalctimings,
 147.439 +
 147.440 +        video_write_null,
 147.441 +        video_write_null,
 147.442 +        pc1512_write,
 147.443 +
 147.444 +        video_read_null,
 147.445 +        video_read_null,
 147.446 +        pc1512_read
 147.447 +};
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/src/vid_pc1640.c	Sun Apr 21 14:54:35 2013 +0100
   148.3 @@ -0,0 +1,97 @@
   148.4 +/*PC1640 video emulation.
   148.5 +  Mostly standard EGA, but with CGA & Hercules emulation*/
   148.6 +#include "ibm.h"
   148.7 +#include "video.h"
   148.8 +#include "vid_cga.h"
   148.9 +#include "vid_ega.h"
  148.10 +
  148.11 +static int pc1640_cga=1;
  148.12 +
  148.13 +void pc1640_out(uint16_t addr, uint8_t val)
  148.14 +{
  148.15 +        switch (addr)
  148.16 +        {
  148.17 +                case 0x3DB:
  148.18 +                pc1640_cga=val&0x40;
  148.19 +                mem_removehandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  148.20 +                mem_removehandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL);
  148.21 +                if (pc1640_cga)
  148.22 +                   mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL);
  148.23 +                else
  148.24 +                {                
  148.25 +                        switch (gdcreg[6] & 0xC)
  148.26 +                        {
  148.27 +                                case 0x0: /*128k at A0000*/
  148.28 +                                mem_sethandler(0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  148.29 +                                break;
  148.30 +                                case 0x4: /*64k at A0000*/
  148.31 +                                mem_sethandler(0xa0000, 0x10000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  148.32 +                                break;
  148.33 +                                case 0x8: /*32k at B0000*/
  148.34 +                                mem_sethandler(0xb0000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  148.35 +                                break;
  148.36 +                                case 0xC: /*32k at B8000*/
  148.37 +                                mem_sethandler(0xb8000, 0x08000, ega_read, NULL, NULL, ega_write, NULL, NULL);
  148.38 +                                break;
  148.39 +                        }
  148.40 +                }                
  148.41 +                pclog("3DB write %02X\n", val);
  148.42 +                return;
  148.43 +        }
  148.44 +        if (pc1640_cga) cga_out(addr,val);
  148.45 +        else            ega_out(addr,val);
  148.46 +}
  148.47 +
  148.48 +uint8_t pc1640_in(uint16_t addr)
  148.49 +{
  148.50 +        switch (addr)
  148.51 +        {
  148.52 +        }
  148.53 +        if (pc1640_cga) return cga_in(addr);
  148.54 +        else            return ega_in(addr);
  148.55 +}
  148.56 +
  148.57 +void pc1640_recalctimings()
  148.58 +{
  148.59 +        if (pc1640_cga) cga_recalctimings();
  148.60 +        else            ega_recalctimings();
  148.61 +}
  148.62 +
  148.63 +void pc1640_poll()
  148.64 +{
  148.65 +        if (pc1640_cga) cga_poll();
  148.66 +        else            ega_poll();
  148.67 +}
  148.68 +
  148.69 +int pc1640_init()
  148.70 +{
  148.71 +        int r = ega_init();
  148.72 +        
  148.73 +        pc1640_cga = 1;
  148.74 +        
  148.75 +        mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL);
  148.76 +        
  148.77 +        return r;
  148.78 +}
  148.79 +
  148.80 +GFXCARD vid_pc1640 =
  148.81 +{
  148.82 +        pc1640_init,
  148.83 +        /*IO at 3Cx/3Dx*/
  148.84 +        pc1640_out,
  148.85 +        pc1640_in,
  148.86 +        /*IO at 3Ax/3Bx*/
  148.87 +        video_out_null,
  148.88 +        video_in_null,
  148.89 +
  148.90 +        pc1640_poll,
  148.91 +        pc1640_recalctimings,
  148.92 +
  148.93 +        ega_write,
  148.94 +        video_write_null,
  148.95 +        video_write_null,
  148.96 +
  148.97 +        ega_read,
  148.98 +        video_read_null,
  148.99 +        video_read_null
 148.100 +};
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/src/vid_pc200.c	Sun Apr 21 14:54:35 2013 +0100
   149.3 @@ -0,0 +1,102 @@
   149.4 +/*PC200 video emulation.
   149.5 +  CGA with some NMI stuff. But we don't need that as it's only used for TV and
   149.6 +  LCD displays, and we're emulating a CRT*/
   149.7 +#include "ibm.h"
   149.8 +#include "video.h"
   149.9 +#include "vid_cga.h"
  149.10 +
  149.11 +uint8_t pc200_3dd, pc200_3de, pc200_3df;
  149.12 +
  149.13 +void pc200_out(uint16_t addr, uint8_t val)
  149.14 +{
  149.15 +        uint8_t old;
  149.16 +        switch (addr)
  149.17 +        {
  149.18 +                case 0x3D5:
  149.19 +                if (!(pc200_3de&0x40) && crtcreg<=11)
  149.20 +                {
  149.21 +                        if (pc200_3de&0x80) nmi=1;
  149.22 +                        pc200_3dd=0x20|(crtcreg&0x1F);
  149.23 +                        pc200_3df=val;
  149.24 +                        return;
  149.25 +                }
  149.26 +                old=crtc[crtcreg];
  149.27 +                crtc[crtcreg]=val&crtcmask[crtcreg];
  149.28 +                if (old!=val)
  149.29 +                {
  149.30 +                        if (crtcreg<0xE || crtcreg>0x10)
  149.31 +                        {
  149.32 +                                fullchange=changeframecount;
  149.33 +                                cga_recalctimings();
  149.34 +                        }
  149.35 +                }
  149.36 +                return;
  149.37 +                
  149.38 +                case 0x3D8:
  149.39 +                old = cgamode;
  149.40 +                cgamode=val;
  149.41 +                if ((cgamode ^ old) & 3)
  149.42 +                   cga_recalctimings();
  149.43 +                pc200_3dd|=0x80;
  149.44 +                if (pc200_3de&0x80)
  149.45 +                   nmi=1;
  149.46 +                return;
  149.47 +                
  149.48 +                case 0x3DE:
  149.49 +                pc200_3de=val;
  149.50 +                pc200_3dd=0x1F;
  149.51 +                if (val&0x80) pc200_3dd|=0x40;
  149.52 +                return;
  149.53 +        }
  149.54 +        cga_out(addr,val);
  149.55 +}
  149.56 +
  149.57 +uint8_t pc200_in(uint16_t addr)
  149.58 +{
  149.59 +        uint8_t temp;
  149.60 +        switch (addr)
  149.61 +        {
  149.62 +                case 0x3D8:
  149.63 +                return cgamode;
  149.64 +                
  149.65 +                case 0x3DD:
  149.66 +                temp = pc200_3dd;
  149.67 +                pc200_3dd &= 0x1F;
  149.68 +                return temp;
  149.69 +                
  149.70 +                case 0x3DE:
  149.71 +                return (pc200_3de&0xC7)| 0x18; /*External CGA*/
  149.72 +                
  149.73 +                case 0x3DF:
  149.74 +                return pc200_3df;
  149.75 +        }
  149.76 +        return cga_in(addr);
  149.77 +}
  149.78 +
  149.79 +int pc200_init()
  149.80 +{
  149.81 +        mem_sethandler(0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL);
  149.82 +        return cga_init();
  149.83 +}
  149.84 +
  149.85 +GFXCARD vid_pc200 =
  149.86 +{
  149.87 +        pc200_init,
  149.88 +        /*IO at 3Cx/3Dx*/
  149.89 +        pc200_out,
  149.90 +        pc200_in,
  149.91 +        /*IO at 3Ax/3Bx*/
  149.92 +        video_out_null,
  149.93 +        video_in_null,
  149.94 +
  149.95 +        cga_poll,
  149.96 +        cga_recalctimings,
  149.97 +
  149.98 +        video_write_null,
  149.99 +        video_write_null,
 149.100 +        cga_write,
 149.101 +
 149.102 +        video_read_null,
 149.103 +        video_read_null,
 149.104 +        cga_read
 149.105 +};
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/src/vid_s3.c	Sun Apr 21 14:54:35 2013 +0100
   150.3 @@ -0,0 +1,1533 @@
   150.4 +/*S3 emulation*/
   150.5 +#include "ibm.h"
   150.6 +#include "mem.h"
   150.7 +#include "pci.h"
   150.8 +#include "video.h"
   150.9 +#include "vid_svga.h"
  150.10 +#include "vid_sdac_ramdac.h"
  150.11 +
  150.12 +void s3_updatemapping();
  150.13 +
  150.14 +void s3_accel_write(uint32_t addr, uint8_t val);
  150.15 +void s3_accel_write_w(uint32_t addr, uint16_t val);
  150.16 +void s3_accel_write_l(uint32_t addr, uint32_t val);
  150.17 +uint8_t s3_accel_read(uint32_t addr);
  150.18 +
  150.19 +static uint8_t s3_bank;
  150.20 +static uint8_t s3_ma_ext;
  150.21 +static int s3_width = 1024;
  150.22 +static int s3_bpp = 0;
  150.23 +
  150.24 +static uint8_t s3_id, s3_id_ext;
  150.25 +
  150.26 +void s3_out(uint16_t addr, uint8_t val)
  150.27 +{
  150.28 +        uint8_t old;
  150.29 +
  150.30 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  150.31 +        
  150.32 +//        pclog("S3 out %04X %02X\n", addr, val);
  150.33 +
  150.34 +        switch (addr)
  150.35 +        {
  150.36 +                case 0x3c5:
  150.37 +                if (seqaddr == 4) /*Chain-4 - update banking*/
  150.38 +                {
  150.39 +                        if (val & 8) svgawbank = svgarbank = s3_bank << 16;
  150.40 +                        else         svgawbank = svgarbank = s3_bank << 14;
  150.41 +                }
  150.42 +                break;
  150.43 +                
  150.44 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  150.45 +//                pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
  150.46 +                sdac_ramdac_out(addr,val);
  150.47 +                return;
  150.48 +
  150.49 +                case 0x3D4:
  150.50 +                crtcreg=val&0x7f;
  150.51 +                return;
  150.52 +                case 0x3D5:
  150.53 +//                        if (crtcreg == 0x67) pclog("Write CRTC R%02X %02X\n", crtcreg, val);
  150.54 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
  150.55 +                if (crtcreg >= 0x20 && crtcreg != 0x38 && (crtc[0x38] & 0xcc) != 0x48) return;
  150.56 +                old=crtc[crtcreg];
  150.57 +                crtc[crtcreg]=val;
  150.58 +                switch (crtcreg)
  150.59 +                {
  150.60 +                        case 0x31:
  150.61 +                        s3_ma_ext = (s3_ma_ext & 0x1c) | ((val & 0x30) >> 4);
  150.62 +                        vrammask = (val & 8) ? 0x3fffff : 0x3ffff;
  150.63 +                        break;
  150.64 +                        
  150.65 +                        case 0x50:
  150.66 +                        switch (crtc[0x50] & 0xc1)
  150.67 +                        {
  150.68 +                                case 0x00: s3_width = (crtc[0x31] & 2) ? 2048 : 1024; break;
  150.69 +                                case 0x01: s3_width = 1152; break;
  150.70 +                                case 0x40: s3_width = 640;  break;
  150.71 +                                case 0x80: s3_width = 800;  break;
  150.72 +                                case 0x81: s3_width = 1600; break;
  150.73 +                                case 0xc0: s3_width = 1280; break;
  150.74 +                        }
  150.75 +                        s3_bpp = (crtc[0x50] >> 4) & 3;
  150.76 +                        break;
  150.77 +                        case 0x69:
  150.78 +                        s3_ma_ext = val & 0x1f;
  150.79 +                        break;
  150.80 +                        
  150.81 +                        case 0x35:
  150.82 +                        s3_bank = (s3_bank & 0x70) | (val & 0xf);
  150.83 +//                        pclog("CRTC write R35 %02X\n", val);
  150.84 +                        if (chain4) svgawbank = svgarbank = s3_bank << 16;
  150.85 +                        else        svgawbank = svgarbank = s3_bank << 14;
  150.86 +                        break;
  150.87 +                        case 0x51:
  150.88 +                        s3_bank = (s3_bank & 0x4f) | ((val & 0xc) << 2);
  150.89 +                        if (chain4) svgawbank = svgarbank = s3_bank << 16;
  150.90 +                        else        svgawbank = svgarbank = s3_bank << 14;
  150.91 +                        s3_ma_ext = (s3_ma_ext & ~0xc) | ((val & 3) << 2);
  150.92 +                        break;
  150.93 +                        case 0x6a:
  150.94 +                        s3_bank = val;
  150.95 +//                        pclog("CRTC write R6a %02X\n", val);
  150.96 +                        if (chain4) svgawbank = svgarbank = s3_bank << 16;
  150.97 +                        else        svgawbank = svgarbank = s3_bank << 14;
  150.98 +                        break;
  150.99 +                        
 150.100 +                        case 0x3a:
 150.101 +                        if (val & 0x10) gdcreg[5] |= 0x40; /*Horrible cheat*/
 150.102 +                        break;
 150.103 +                        
 150.104 +                        case 0x45:
 150.105 +                        svga_hwcursor.ena = val & 1;
 150.106 +                        break;
 150.107 +                        case 0x48:
 150.108 +                        svga_hwcursor.x = ((crtc[0x46] << 8) | crtc[0x47]) & 0x7ff;
 150.109 +                        if (bpp == 32) svga_hwcursor.x >>= 1;
 150.110 +                        svga_hwcursor.y = ((crtc[0x48] << 8) | crtc[0x49]) & 0x7ff;
 150.111 +                        svga_hwcursor.xoff = crtc[0x4e] & 63;
 150.112 +                        svga_hwcursor.yoff = crtc[0x4f] & 63;
 150.113 +                        svga_hwcursor.addr = ((((crtc[0x4c] << 8) | crtc[0x4d]) & 0xfff) * 1024) + (svga_hwcursor.yoff * 16);
 150.114 +                        break;
 150.115 +
 150.116 +                        case 0x53:
 150.117 +                        case 0x58: case 0x59: case 0x5a:
 150.118 +                        s3_updatemapping();
 150.119 +                        break;
 150.120 +                        
 150.121 +                        case 0x67:
 150.122 +                        if (gfxcard == GFX_N9_9FX) /*Trio64*/
 150.123 +                        {
 150.124 +                                switch (val >> 4)
 150.125 +                                {
 150.126 +                                        case 3:  bpp = 15; break;
 150.127 +                                        case 5:  bpp = 16; break;
 150.128 +                                        case 7:  bpp = 24; break;
 150.129 +                                        case 13: bpp = 32; break;
 150.130 +                                        default: bpp = 8;  break;
 150.131 +                                }
 150.132 +                        }
 150.133 +                        break;
 150.134 +                        //case 0x55: case 0x43:
 150.135 +//                                pclog("Write CRTC R%02X %02X\n", crtcreg, val);
 150.136 +                }
 150.137 +                if (old!=val)
 150.138 +                {
 150.139 +                        if (crtcreg<0xE || crtcreg>0x10)
 150.140 +                        {
 150.141 +                                fullchange=changeframecount;
 150.142 +                                svga_recalctimings();
 150.143 +                        }
 150.144 +                }
 150.145 +                break;
 150.146 +        }
 150.147 +        svga_out(addr,val);
 150.148 +}
 150.149 +
 150.150 +uint8_t s3_in(uint16_t addr)
 150.151 +{
 150.152 +        uint8_t temp;
 150.153 +
 150.154 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
 150.155 +
 150.156 +//        if (addr != 0x3da) pclog("S3 in %04X\n", addr);
 150.157 +        switch (addr)
 150.158 +        {
 150.159 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
 150.160 +//                pclog("Read RAMDAC %04X  %04X:%04X\n", addr, CS, pc);
 150.161 +                return sdac_ramdac_in(addr);
 150.162 +
 150.163 +                case 0x3D4:
 150.164 +                return crtcreg;
 150.165 +                case 0x3D5:
 150.166 +//                pclog("Read CRTC R%02X %04X:%04X\n", crtcreg, CS, pc);
 150.167 +                switch (crtcreg)
 150.168 +                {
 150.169 +                        case 0x2d: return 0x88;      /*Extended chip ID*/
 150.170 +                        case 0x2e: return s3_id_ext; /*New chip ID*/
 150.171 +                        case 0x30: return s3_id;     /*Chip ID*/
 150.172 +                        case 0x31: return (crtc[0x31] & 0xcf) | ((s3_ma_ext & 3) << 4);
 150.173 +                        case 0x35: return (crtc[0x35] & 0xf0) | (s3_bank & 0xf);
 150.174 +                        case 0x51: return (crtc[0x51] & 0xf0) | ((s3_bank >> 2) & 0xc) | ((s3_ma_ext >> 2) & 3);
 150.175 +                        case 0x69: return s3_ma_ext;
 150.176 +                        case 0x6a: return s3_bank;
 150.177 +                }
 150.178 +                return crtc[crtcreg];
 150.179 +        }
 150.180 +        return svga_in(addr);
 150.181 +}
 150.182 +
 150.183 +void s3_recalctimings()
 150.184 +{
 150.185 +//        pclog("recalctimings\n");
 150.186 +        svga_ma |= (s3_ma_ext << 16);
 150.187 +//        pclog("SVGA_MA %08X\n", svga_ma);
 150.188 +        if (gdcreg[5] & 0x40) svga_lowres = !(crtc[0x3a] & 0x10);
 150.189 +        if (crtc[0x5d] & 0x01) svga_htotal     += 0x100;
 150.190 +        if (crtc[0x5d] & 0x02) svga_hdisp      += 0x100;
 150.191 +        if (crtc[0x5e] & 0x01) svga_vtotal     += 0x400;
 150.192 +        if (crtc[0x5e] & 0x02) svga_dispend    += 0x400;
 150.193 +        if (crtc[0x5e] & 0x10) svga_vsyncstart += 0x400;
 150.194 +        if (crtc[0x5e] & 0x40) svga_split      += 0x400;
 150.195 +        if (crtc[0x51] & 0x30)      svga_rowoffset  += (crtc[0x51] & 0x30) << 4;
 150.196 +        else if (crtc[0x43] & 0x04) svga_rowoffset  += 0x100;
 150.197 +        if (!svga_rowoffset) svga_rowoffset = 256;
 150.198 +        svga_interlace = crtc[0x42] & 0x20;
 150.199 +        svga_clock = cpuclock / sdac_getclock((svga_miscout >> 2) & 3);
 150.200 +//        pclog("SVGA_CLOCK = %f  %02X  %f\n", svga_clock, svga_miscout, cpuclock);
 150.201 +        if (bpp > 8) svga_clock /= 2;
 150.202 +}
 150.203 +
 150.204 +static uint32_t s3_linear_base = 0, s3_linear_size = 0;
 150.205 +void s3_updatemapping()
 150.206 +{
 150.207 +        mem_removehandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear);
 150.208 +        
 150.209 +//        video_write_a000_w = video_write_a000_l = NULL;
 150.210 +
 150.211 +        mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.212 +//        pclog("Update mapping - bank %02X ", gdcreg[6] & 0xc);        
 150.213 +        switch (gdcreg[6] & 0xc) /*Banked framebuffer*/
 150.214 +        {
 150.215 +                case 0x0: /*128k at A0000*/
 150.216 +                mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.217 +                break;
 150.218 +                case 0x4: /*64k at A0000*/
 150.219 +                mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.220 +                break;
 150.221 +                case 0x8: /*32k at B0000*/
 150.222 +                mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.223 +                break;
 150.224 +                case 0xC: /*32k at B8000*/
 150.225 +                mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.226 +                break;
 150.227 +        }
 150.228 +        
 150.229 +//        pclog("Linear framebuffer %02X ", crtc[0x58] & 0x10);
 150.230 +        if (crtc[0x58] & 0x10) /*Linear framebuffer*/
 150.231 +        {
 150.232 +                s3_linear_base = (crtc[0x5a] << 16) | (crtc[0x59] << 24);
 150.233 +                switch (crtc[0x58] & 3)
 150.234 +                {
 150.235 +                        case 0: /*64k*/
 150.236 +                        s3_linear_size = 0x10000;
 150.237 +                        break;
 150.238 +                        case 1: /*1mb*/
 150.239 +                        s3_linear_size = 0x100000;
 150.240 +                        break;
 150.241 +                        case 2: /*2mb*/
 150.242 +                        s3_linear_size = 0x200000;
 150.243 +                        break;
 150.244 +                        case 3: /*8mb*/
 150.245 +                        s3_linear_size = 0x800000;
 150.246 +                        break;
 150.247 +                }
 150.248 +                s3_linear_base &= ~(s3_linear_size - 1);
 150.249 +//                pclog("%08X %08X  %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
 150.250 +//                pclog("Linear framebuffer at %08X size %08X\n", linear_base, linear_size);
 150.251 +                if (s3_linear_base == 0xa0000)
 150.252 +                   mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 150.253 +                else
 150.254 +                   mem_sethandler(s3_linear_base, s3_linear_size, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear);
 150.255 +        }
 150.256 +        
 150.257 +//        pclog("Memory mapped IO %02X\n", crtc[0x53] & 0x10);
 150.258 +        if (crtc[0x53] & 0x10) /*Memory mapped IO*/
 150.259 +        {
 150.260 +                mem_sethandler(0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l);
 150.261 +/*                video_write_a000   = s3_accel_write;
 150.262 +                video_write_a000_w = s3_accel_write_w;
 150.263 +                video_write_a000_l = s3_accel_write_l;
 150.264 +                video_read_a000    = s3_accel_read;*/
 150.265 +        }
 150.266 +}
 150.267 +
 150.268 +
 150.269 +struct
 150.270 +{
 150.271 +        uint8_t subsys_cntl;
 150.272 +        uint8_t setup_md;
 150.273 +        uint8_t advfunc_cntl;
 150.274 +        uint16_t cur_y;
 150.275 +        uint16_t cur_x;
 150.276 +         int16_t desty_axstp;
 150.277 +         int16_t destx_distp;
 150.278 +         int16_t err_term;
 150.279 +         int16_t maj_axis_pcnt;
 150.280 +        uint16_t cmd;
 150.281 +        uint16_t short_stroke;
 150.282 +        uint32_t bkgd_color;
 150.283 +        uint32_t frgd_color;
 150.284 +        uint32_t wrt_mask;
 150.285 +        uint32_t rd_mask;
 150.286 +        uint32_t color_cmp;
 150.287 +        uint8_t bkgd_mix;
 150.288 +        uint8_t frgd_mix;
 150.289 +        uint16_t multifunc_cntl;
 150.290 +        uint16_t multifunc[16];
 150.291 +        uint8_t pix_trans[4];
 150.292 +        
 150.293 +        int cx, cy;
 150.294 +        int sx, sy;
 150.295 +        int dx, dy;
 150.296 +        uint32_t src, dest, pattern;
 150.297 +        int pix_trans_count;
 150.298 +        
 150.299 +        uint32_t dat_buf;
 150.300 +        int dat_count;
 150.301 +} s3_accel;
 150.302 +
 150.303 +void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat);
 150.304 +
 150.305 +void s3_accel_out(uint16_t port, uint8_t val)
 150.306 +{
 150.307 +//        pclog("Accel out %04X %02X\n", port, val);
 150.308 +        switch (port)
 150.309 +        {
 150.310 +                case 0x42e8:
 150.311 +                break;
 150.312 +                case 0x42e9:
 150.313 +                s3_accel.subsys_cntl = val;
 150.314 +                break;
 150.315 +                case 0x46e8:
 150.316 +                s3_accel.setup_md = val;
 150.317 +                break;
 150.318 +                case 0x4ae8:
 150.319 +                s3_accel.advfunc_cntl = val;
 150.320 +                break;
 150.321 +                
 150.322 +                case 0x82e8:
 150.323 +                s3_accel.cur_y = (s3_accel.cur_y & 0xf00) | val;
 150.324 +                break;
 150.325 +                case 0x82e9:
 150.326 +                s3_accel.cur_y = (s3_accel.cur_y & 0xff) | ((val & 0x1f) << 8);
 150.327 +                break;
 150.328 +                
 150.329 +                case 0x86e8:
 150.330 +                s3_accel.cur_x = (s3_accel.cur_x & 0xf00) | val;
 150.331 +                break;
 150.332 +                case 0x86e9:
 150.333 +                s3_accel.cur_x = (s3_accel.cur_x & 0xff) | ((val & 0x1f) << 8);
 150.334 +                break;
 150.335 +                
 150.336 +                case 0x8ae8:
 150.337 +                s3_accel.desty_axstp = (s3_accel.desty_axstp & 0x3f00) | val;
 150.338 +                break;
 150.339 +                case 0x8ae9:
 150.340 +                s3_accel.desty_axstp = (s3_accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
 150.341 +                if (val & 0x20)
 150.342 +                   s3_accel.desty_axstp |= ~0x3fff;
 150.343 +                break;
 150.344 +                
 150.345 +                case 0x8ee8:
 150.346 +                s3_accel.destx_distp = (s3_accel.destx_distp & 0x3f00) | val;
 150.347 +                break;
 150.348 +                case 0x8ee9:
 150.349 +                s3_accel.destx_distp = (s3_accel.destx_distp & 0xff) | ((val & 0x3f) << 8);
 150.350 +                if (val & 0x20)
 150.351 +                   s3_accel.destx_distp |= ~0x3fff;
 150.352 +                break;
 150.353 +                
 150.354 +                case 0x92e8:
 150.355 +                s3_accel.err_term = (s3_accel.err_term & 0x3f00) | val;
 150.356 +                break;
 150.357 +                case 0x92e9:
 150.358 +                s3_accel.err_term = (s3_accel.err_term & 0xff) | ((val & 0x3f) << 8);
 150.359 +                if (val & 0x20)
 150.360 +                   s3_accel.err_term |= ~0x3fff;
 150.361 +                break;
 150.362 +
 150.363 +                case 0x96e8:
 150.364 +                s3_accel.maj_axis_pcnt = (s3_accel.maj_axis_pcnt & 0x3f00) | val;
 150.365 +                break;
 150.366 +                case 0x96e9:
 150.367 +                s3_accel.maj_axis_pcnt = (s3_accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8);
 150.368 +                if (val & 0x08)
 150.369 +                   s3_accel.maj_axis_pcnt |= ~0x0fff;
 150.370 +                break;
 150.371 +
 150.372 +                case 0x9ae8:
 150.373 +                s3_accel.cmd = (s3_accel.cmd & 0xff00) | val;
 150.374 +                break;
 150.375 +                case 0x9ae9:
 150.376 +                s3_accel.cmd = (s3_accel.cmd & 0xff) | (val << 8);
 150.377 +                s3_accel_start(-1, 0, 0xffffffff, 0);
 150.378 +                s3_accel.pix_trans_count = 0;
 150.379 +                break;
 150.380 +
 150.381 +                case 0x9ee8:
 150.382 +                s3_accel.short_stroke = (s3_accel.short_stroke & 0xff00) | val;
 150.383 +                break;
 150.384 +                case 0x9ee9:
 150.385 +                s3_accel.short_stroke = (s3_accel.short_stroke & 0xff) | (val << 8);
 150.386 +                break;
 150.387 +
 150.388 +                case 0xa2e8:
 150.389 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.390 +                   s3_accel.bkgd_color = (s3_accel.bkgd_color & ~0x00ff0000) | (val << 16);
 150.391 +                else
 150.392 +                   s3_accel.bkgd_color = (s3_accel.bkgd_color & ~0x000000ff) | val;
 150.393 +                break;
 150.394 +                case 0xa2e9:
 150.395 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.396 +                   s3_accel.bkgd_color = (s3_accel.bkgd_color & ~0xff000000) | (val << 24);
 150.397 +                else
 150.398 +                   s3_accel.bkgd_color = (s3_accel.bkgd_color & ~0x0000ff00) | (val << 8);
 150.399 +                s3_accel.multifunc[0xe] ^= 0x10;
 150.400 +                break;
 150.401 +
 150.402 +                case 0xa6e8:
 150.403 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.404 +                   s3_accel.frgd_color = (s3_accel.frgd_color & ~0x00ff0000) | (val << 16);
 150.405 +                else
 150.406 +                   s3_accel.frgd_color = (s3_accel.frgd_color & ~0x000000ff) | val;
 150.407 +//                pclog("Foreground colour now %08X %i\n", s3_accel.frgd_color, s3_bpp);
 150.408 +                break;
 150.409 +                case 0xa6e9:
 150.410 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.411 +                   s3_accel.frgd_color = (s3_accel.frgd_color & ~0xff000000) | (val << 24);
 150.412 +                else
 150.413 +                   s3_accel.frgd_color = (s3_accel.frgd_color & ~0x0000ff00) | (val << 8);
 150.414 +                s3_accel.multifunc[0xe] ^= 0x10;
 150.415 +//                pclog("Foreground colour now %08X\n", s3_accel.frgd_color);
 150.416 +                break;
 150.417 +
 150.418 +                case 0xaae8:
 150.419 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.420 +                   s3_accel.wrt_mask = (s3_accel.wrt_mask & ~0x00ff0000) | (val << 16);
 150.421 +                else
 150.422 +                   s3_accel.wrt_mask = (s3_accel.wrt_mask & ~0x000000ff) | val;
 150.423 +                break;
 150.424 +                case 0xaae9:
 150.425 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.426 +                   s3_accel.wrt_mask = (s3_accel.wrt_mask & ~0xff000000) | (val << 24);
 150.427 +                else
 150.428 +                   s3_accel.wrt_mask = (s3_accel.wrt_mask & ~0x0000ff00) | (val << 8);
 150.429 +                s3_accel.multifunc[0xe] ^= 0x10;
 150.430 +                break;
 150.431 +
 150.432 +                case 0xaee8:
 150.433 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.434 +                   s3_accel.rd_mask = (s3_accel.rd_mask & ~0x00ff0000) | (val << 16);
 150.435 +                else
 150.436 +                   s3_accel.rd_mask = (s3_accel.rd_mask & ~0x000000ff) | val;
 150.437 +                break;
 150.438 +                case 0xaee9:
 150.439 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.440 +                   s3_accel.rd_mask = (s3_accel.rd_mask & ~0xff000000) | (val << 24);
 150.441 +                else
 150.442 +                   s3_accel.rd_mask = (s3_accel.rd_mask & ~0x0000ff00) | (val << 8);
 150.443 +                s3_accel.multifunc[0xe] ^= 0x10;
 150.444 +                break;
 150.445 +
 150.446 +                case 0xb2e8:
 150.447 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.448 +                   s3_accel.color_cmp = (s3_accel.color_cmp & ~0x00ff0000) | (val << 16);
 150.449 +                else
 150.450 +                   s3_accel.color_cmp = (s3_accel.color_cmp & ~0x000000ff) | val;
 150.451 +                break;
 150.452 +                case 0xb2e9:
 150.453 +                if (s3_bpp == 3 && s3_accel.multifunc[0xe] & 0x10)
 150.454 +                   s3_accel.color_cmp = (s3_accel.color_cmp & ~0xff000000) | (val << 24);
 150.455 +                else
 150.456 +                   s3_accel.color_cmp = (s3_accel.color_cmp & ~0x0000ff00) | (val << 8);
 150.457 +                s3_accel.multifunc[0xe] ^= 0x10;
 150.458 +                break;
 150.459 +
 150.460 +                case 0xb6e8:
 150.461 +                s3_accel.bkgd_mix = val;
 150.462 +                break;
 150.463 +
 150.464 +                case 0xbae8:
 150.465 +                s3_accel.frgd_mix = val;
 150.466 +                break;
 150.467 +                
 150.468 +                case 0xbee8:
 150.469 +                s3_accel.multifunc_cntl = (s3_accel.multifunc_cntl & 0xff00) | val;
 150.470 +                break;
 150.471 +                case 0xbee9:
 150.472 +                s3_accel.multifunc_cntl = (s3_accel.multifunc_cntl & 0xff) | (val << 8);
 150.473 +                s3_accel.multifunc[s3_accel.multifunc_cntl >> 12] = s3_accel.multifunc_cntl & 0xfff;
 150.474 +                break;
 150.475 +
 150.476 +                case 0xe2e8:
 150.477 +                s3_accel.pix_trans[0] = val;
 150.478 +                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3_accel.cmd & 0x600) && (s3_accel.cmd & 0x100))
 150.479 +                   s3_accel_start(8, 1, s3_accel.pix_trans[0], 0);
 150.480 +                else if (!(s3_accel.cmd & 0x600) && (s3_accel.cmd & 0x100))
 150.481 +                   s3_accel_start(1, 1, 0xffffffff, s3_accel.pix_trans[0]);
 150.482 +                break;
 150.483 +                case 0xe2e9:
 150.484 +                s3_accel.pix_trans[1] = val;
 150.485 +                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && (s3_accel.cmd & 0x600) == 0x200 && (s3_accel.cmd & 0x100))
 150.486 +                {
 150.487 +                        if (s3_accel.cmd & 0x1000) s3_accel_start(16, 1, s3_accel.pix_trans[1] | (s3_accel.pix_trans[0] << 8), 0);
 150.488 +                        else                       s3_accel_start(16, 1, s3_accel.pix_trans[0] | (s3_accel.pix_trans[1] << 8), 0);
 150.489 +                }
 150.490 +                else if ((s3_accel.cmd & 0x600) == 0x200 && (s3_accel.cmd & 0x100))
 150.491 +                {
 150.492 +                        if (s3_accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3_accel.pix_trans[1] | (s3_accel.pix_trans[0] << 8));
 150.493 +                        else                       s3_accel_start(2, 1, 0xffffffff, s3_accel.pix_trans[0] | (s3_accel.pix_trans[1] << 8));
 150.494 +                }
 150.495 +                break;
 150.496 +                case 0xe2ea:
 150.497 +                s3_accel.pix_trans[2] = val;
 150.498 +                break;
 150.499 +                case 0xe2eb:
 150.500 +                s3_accel.pix_trans[3] = val;
 150.501 +                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && (s3_accel.cmd & 0x600) == 0x400 && (s3_accel.cmd & 0x100))
 150.502 +                   s3_accel_start(32, 1, s3_accel.pix_trans[0] | (s3_accel.pix_trans[1] << 8) | (s3_accel.pix_trans[2] << 16) | (s3_accel.pix_trans[3] << 24), 0);
 150.503 +                else if ((s3_accel.cmd & 0x600) == 0x400 && (s3_accel.cmd & 0x100))
 150.504 +                   s3_accel_start(4, 1, 0xffffffff, s3_accel.pix_trans[0] | (s3_accel.pix_trans[1] << 8) | (s3_accel.pix_trans[2] << 16) | (s3_accel.pix_trans[3] << 24));
 150.505 +                break;
 150.506 +        }
 150.507 +}
 150.508 +
 150.509 +void s3_accel_out_w(uint16_t port, uint16_t val)
 150.510 +{
 150.511 +//        pclog("Accel out w %04X %04X\n", port, val);
 150.512 +        if (s3_accel.cmd & 0x100)
 150.513 +        {
 150.514 +                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80)
 150.515 +                {
 150.516 +                        if (s3_accel.cmd & 0x1000)
 150.517 +                           val = (val >> 8) | (val << 8);
 150.518 +                        s3_accel_start(16, 1, val | (val << 16), 0);
 150.519 +                }
 150.520 +                else
 150.521 +                   s3_accel_start(2, 1, 0xffffffff, val | (val << 16));
 150.522 +        }
 150.523 +}
 150.524 +
 150.525 +void s3_accel_out_l(uint16_t port, uint32_t val)
 150.526 +{
 150.527 +//        pclog("Accel out l %04X %08X\n", port, val);
 150.528 +        if (s3_accel.cmd & 0x100)
 150.529 +        {
 150.530 +                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80)
 150.531 +                {
 150.532 +                        if (s3_accel.cmd & 0x1000)
 150.533 +                           val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
 150.534 +                        if ((s3_accel.cmd & 0x600) == 0x400)
 150.535 +                           s3_accel_start(32, 1, val, 0);
 150.536 +                        else if ((s3_accel.cmd & 0x600) == 0x200)
 150.537 +                        {
 150.538 +                                s3_accel_start(16, 1, val >> 16, 0);
 150.539 +                                s3_accel_start(16, 1, val, 0);
 150.540 +                        }
 150.541 +                        else if (!(s3_accel.cmd & 0x600))
 150.542 +                        {
 150.543 +                                s3_accel_start(8, 1, val >> 24, 0);
 150.544 +                                s3_accel_start(8, 1, val >> 16, 0);
 150.545 +                                s3_accel_start(8, 1, val >> 8,  0);
 150.546 +                                s3_accel_start(8, 1, val,       0);
 150.547 +                        }
 150.548 +                }
 150.549 +                else
 150.550 +                {
 150.551 +                        if ((s3_accel.cmd & 0x600) == 0x400)
 150.552 +                           s3_accel_start(4, 1, 0xffffffff, val);
 150.553 +                        else if ((s3_accel.cmd & 0x600) == 0x200)
 150.554 +                        {
 150.555 +                                s3_accel_start(2, 1, 0xffffffff, val >> 16);
 150.556 +                                s3_accel_start(2, 1, 0xffffffff, val);
 150.557 +                        }
 150.558 +                        else if (!(s3_accel.cmd & 0x600))
 150.559 +                        {
 150.560 +                                s3_accel_start(1, 1, 0xffffffff, val >> 24);
 150.561 +                                s3_accel_start(1, 1, 0xffffffff, val >> 16);
 150.562 +                                s3_accel_start(1, 1, 0xffffffff, val >> 8);
 150.563 +                                s3_accel_start(1, 1, 0xffffffff, val);
 150.564 +                        }
 150.565 +                }
 150.566 +        }
 150.567 +}
 150.568 +
 150.569 +uint8_t s3_accel_in(uint16_t port)
 150.570 +{
 150.571 +        int temp;
 150.572 +//        pclog("Accel in  %04X\n", port);
 150.573 +        switch (port)
 150.574 +        {
 150.575 +                case 0x42e8:
 150.576 +                return 0;
 150.577 +                case 0x42e9:
 150.578 +                return 0;
 150.579 +
 150.580 +                case 0x82e8:
 150.581 +                return s3_accel.cur_y & 0xff;
 150.582 +                case 0x82e9:
 150.583 +                return s3_accel.cur_y  >> 8;
 150.584 +
 150.585 +                case 0x86e8:
 150.586 +                return s3_accel.cur_x & 0xff;
 150.587 +                case 0x86e9:
 150.588 +                return s3_accel.cur_x  >> 8;
 150.589 +
 150.590 +                case 0x8ae8:
 150.591 +                return s3_accel.desty_axstp & 0xff;
 150.592 +                case 0x8ae9:
 150.593 +                return s3_accel.desty_axstp >> 8;
 150.594 +
 150.595 +                case 0x8ee8:
 150.596 +                return s3_accel.destx_distp & 0xff;
 150.597 +                case 0x8ee9:
 150.598 +                return s3_accel.destx_distp >> 8;
 150.599 +
 150.600 +                case 0x92e8:
 150.601 +                return s3_accel.err_term & 0xff;
 150.602 +                case 0x92e9:
 150.603 +                return s3_accel.err_term >> 8;
 150.604 +
 150.605 +                case 0x96e8:
 150.606 +                return s3_accel.maj_axis_pcnt & 0xff;
 150.607 +                case 0x96e9:
 150.608 +                return s3_accel.maj_axis_pcnt >> 8;
 150.609 +
 150.610 +                case 0x9ae8:
 150.611 +                return 0;
 150.612 +                case 0x9ae9:
 150.613 +                return 0;
 150.614 +
 150.615 +                case 0xa2e8:
 150.616 +                return s3_accel.bkgd_color & 0xff;
 150.617 +                case 0xa2e9:
 150.618 +                return s3_accel.bkgd_color >> 8;
 150.619 +
 150.620 +                case 0xa6e8:
 150.621 +                return s3_accel.frgd_color & 0xff;
 150.622 +                case 0xa6e9:
 150.623 +                return s3_accel.frgd_color >> 8;
 150.624 +
 150.625 +                case 0xaae8:
 150.626 +                return s3_accel.wrt_mask & 0xff;
 150.627 +                case 0xaae9:
 150.628 +                return s3_accel.wrt_mask >> 8;
 150.629 +
 150.630 +                case 0xaee8:
 150.631 +                return s3_accel.rd_mask & 0xff;
 150.632 +                case 0xaee9:
 150.633 +                return s3_accel.rd_mask >> 8;
 150.634 +
 150.635 +                case 0xb2e8:
 150.636 +                return s3_accel.color_cmp & 0xff;
 150.637 +                case 0xb2e9:
 150.638 +                return s3_accel.color_cmp >> 8;
 150.639 +
 150.640 +                case 0xb6e8:
 150.641 +                return s3_accel.bkgd_mix;
 150.642 +
 150.643 +                case 0xbae8:
 150.644 +                return s3_accel.frgd_mix;
 150.645 +
 150.646 +                case 0xbee8:
 150.647 +                temp = s3_accel.multifunc[0xf] & 0xf;
 150.648 +                switch (temp)
 150.649 +                {
 150.650 +                        case 0x0: return s3_accel.multifunc[0x0] & 0xff;
 150.651 +                        case 0x1: return s3_accel.multifunc[0x1] & 0xff;
 150.652 +                        case 0x2: return s3_accel.multifunc[0x2] & 0xff;
 150.653 +                        case 0x3: return s3_accel.multifunc[0x3] & 0xff;
 150.654 +                        case 0x4: return s3_accel.multifunc[0x4] & 0xff;
 150.655 +                        case 0x5: return s3_accel.multifunc[0xa] & 0xff;
 150.656 +                        case 0x6: return s3_accel.multifunc[0xe] & 0xff;
 150.657 +                        case 0x7: return s3_accel.cmd            & 0xff;
 150.658 +                        case 0x8: return s3_accel.subsys_cntl    & 0xff;
 150.659 +                        case 0x9: return s3_accel.setup_md       & 0xff;
 150.660 +                        case 0xa: return s3_accel.multifunc[0xd] & 0xff;
 150.661 +                }
 150.662 +                return 0xff;
 150.663 +                case 0xbee9:
 150.664 +                temp = s3_accel.multifunc[0xf] & 0xf;
 150.665 +                s3_accel.multifunc[0xf]++;
 150.666 +                switch (temp)
 150.667 +                {
 150.668 +                        case 0x0: return  s3_accel.multifunc[0x0] >> 8;
 150.669 +                        case 0x1: return  s3_accel.multifunc[0x1] >> 8;
 150.670 +                        case 0x2: return  s3_accel.multifunc[0x2] >> 8;
 150.671 +                        case 0x3: return  s3_accel.multifunc[0x3] >> 8;
 150.672 +                        case 0x4: return  s3_accel.multifunc[0x4] >> 8;
 150.673 +                        case 0x5: return  s3_accel.multifunc[0xa] >> 8;
 150.674 +                        case 0x6: return  s3_accel.multifunc[0xe] >> 8;
 150.675 +                        case 0x7: return  s3_accel.cmd            >> 8;
 150.676 +                        case 0x8: return (s3_accel.subsys_cntl    >> 8) & ~0xe000;
 150.677 +                        case 0x9: return (s3_accel.setup_md       >> 8) & ~0xf000;
 150.678 +                        case 0xa: return  s3_accel.multifunc[0xd] >> 8;
 150.679 +                }
 150.680 +                return 0xff;
 150.681 +
 150.682 +                case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/
 150.683 +                break;
 150.684 +        }
 150.685 +        return 0;
 150.686 +}
 150.687 +
 150.688 +void s3_accel_write(uint32_t addr, uint8_t val)
 150.689 +{
 150.690 +//        pclog("Write S3 accel %08X %02X\n", addr, val);
 150.691 +        if (addr & 0x8000)
 150.692 +           s3_accel_out(addr & 0xffff, val);
 150.693 +        else
 150.694 +        {
 150.695 +                if (s3_accel.cmd & 0x100)
 150.696 +                {
 150.697 +                        if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80)
 150.698 +                           s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0);
 150.699 +                        else
 150.700 +                           s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24));
 150.701 +                }
 150.702 +        }
 150.703 +}
 150.704 +
 150.705 +void s3_accel_write_w(uint32_t addr, uint16_t val)
 150.706 +{
 150.707 +//        pclog("Write S3 accel w %08X %04X\n", addr, val);
 150.708 +        if (addr & 0x8000)
 150.709 +        {
 150.710 +                s3_accel_out( addr & 0xffff,      val);
 150.711 +                s3_accel_out((addr & 0xffff) + 1, val >> 8);
 150.712 +        }
 150.713 +        else
 150.714 +        {
 150.715 +                if (s3_accel.cmd & 0x100)
 150.716 +                {
 150.717 +                        if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80)
 150.718 +                        {
 150.719 +                                if (s3_accel.cmd & 0x1000)
 150.720 +                                   val = (val >> 8) | (val << 8);
 150.721 +                                s3_accel_start(16, 1, val | (val << 16), 0);
 150.722 +                        }
 150.723 +                        else
 150.724 +                           s3_accel_start(2, 1, 0xffffffff, val | (val << 16));
 150.725 +                }
 150.726 +        }
 150.727 +}
 150.728 +
 150.729 +void s3_accel_write_l(uint32_t addr, uint32_t val)
 150.730 +{
 150.731 +//        pclog("Write S3 accel l %08X %08X\n", addr, val);
 150.732 +        if (addr & 0x8000)
 150.733 +        {
 150.734 +                s3_accel_out( addr & 0xffff,      val);
 150.735 +                s3_accel_out((addr & 0xffff) + 1, val >> 8);
 150.736 +                s3_accel_out((addr & 0xffff) + 2, val >> 16);
 150.737 +                s3_accel_out((addr & 0xffff) + 3, val >> 24);
 150.738 +        }
 150.739 +        else
 150.740 +        {
 150.741 +                if (s3_accel.cmd & 0x100)
 150.742 +                {
 150.743 +                        if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80)
 150.744 +                        {
 150.745 +                                if (s3_accel.cmd & 0x1000)
 150.746 +                                   val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
 150.747 +                                if ((s3_accel.cmd & 0x600) == 0x400)
 150.748 +                                   s3_accel_start(32, 1, val, 0);
 150.749 +                                else if ((s3_accel.cmd & 0x600) == 0x200)
 150.750 +                                {
 150.751 +                                        s3_accel_start(16, 1, val >> 16, 0);
 150.752 +                                        s3_accel_start(16, 1, val, 0);
 150.753 +                                }
 150.754 +                                else if (!(s3_accel.cmd & 0x600))
 150.755 +                                {
 150.756 +                                        s3_accel_start(8, 1, val >> 24, 0);
 150.757 +                                        s3_accel_start(8, 1, val >> 16, 0);
 150.758 +                                        s3_accel_start(8, 1, val >> 8,  0);
 150.759 +                                        s3_accel_start(8, 1, val,       0);
 150.760 +                                }
 150.761 +                        }
 150.762 +                        else
 150.763 +                        {
 150.764 +                                if ((s3_accel.cmd & 0x600) == 0x400)
 150.765 +                                   s3_accel_start(4, 1, 0xffffffff, val);
 150.766 +                                else if ((s3_accel.cmd & 0x600) == 0x200)
 150.767 +                                {
 150.768 +                                        s3_accel_start(2, 1, 0xffffffff, val >> 16);
 150.769 +                                        s3_accel_start(2, 1, 0xffffffff, val);
 150.770 +                                }
 150.771 +                                else if (!(s3_accel.cmd & 0x600))
 150.772 +                                {
 150.773 +                                        s3_accel_start(1, 1, 0xffffffff, val >> 24);
 150.774 +                                        s3_accel_start(1, 1, 0xffffffff, val >> 16);
 150.775 +                                        s3_accel_start(1, 1, 0xffffffff, val >> 8);
 150.776 +                                        s3_accel_start(1, 1, 0xffffffff, val);
 150.777 +                                }
 150.778 +                        }
 150.779 +                }
 150.780 +        }
 150.781 +}
 150.782 +
 150.783 +uint8_t s3_accel_read(uint32_t addr)
 150.784 +{
 150.785 +//        pclog("Read S3 accel %08X\n", addr);
 150.786 +        if (addr & 0x8000)
 150.787 +           return s3_accel_in(addr & 0xffff);
 150.788 +        return 0;
 150.789 +}
 150.790 +
 150.791 +#define READ(addr, dat) if (s3_bpp == 0)      dat = vram[  (addr) & 0x3fffff]; \
 150.792 +                        else if (s3_bpp == 1) dat = vram_w[(addr) & 0x1fffff]; \
 150.793 +                        else                  dat = vram_l[(addr) & 0x0fffff];
 150.794 +
 150.795 +#define MIX     switch ((mix_dat & mix_mask) ? (s3_accel.frgd_mix & 0xf) : (s3_accel.bkgd_mix & 0xf))   \
 150.796 +                {                                                                                       \
 150.797 +                        case 0x0: dest_dat =             ~dest_dat;  break;                             \
 150.798 +                        case 0x1: dest_dat =  0;                     break;                             \
 150.799 +                        case 0x2: dest_dat =  1;                     break;                             \
 150.800 +                        case 0x3: dest_dat =              dest_dat;  break;                             \
 150.801 +                        case 0x4: dest_dat =  ~src_dat;              break;                             \
 150.802 +                        case 0x5: dest_dat =   src_dat ^  dest_dat;  break;                             \
 150.803 +                        case 0x6: dest_dat = ~(src_dat ^  dest_dat); break;                             \
 150.804 +                        case 0x7: dest_dat =   src_dat;              break;                             \
 150.805 +                        case 0x8: dest_dat = ~(src_dat &  dest_dat); break;                             \
 150.806 +                        case 0x9: dest_dat =  ~src_dat |  dest_dat;  break;                             \
 150.807 +                        case 0xa: dest_dat =   src_dat | ~dest_dat;  break;                             \
 150.808 +                        case 0xb: dest_dat =   src_dat |  dest_dat;  break;                             \
 150.809 +                        case 0xc: dest_dat =   src_dat &  dest_dat;  break;                             \
 150.810 +                        case 0xd: dest_dat =   src_dat & ~dest_dat;  break;                             \
 150.811 +                        case 0xe: dest_dat =  ~src_dat &  dest_dat;  break;                             \
 150.812 +                        case 0xf: dest_dat = ~(src_dat |  dest_dat); break;                             \
 150.813 +                }
 150.814 +
 150.815 +
 150.816 +#define WRITE(addr)     if (s3_bpp == 0)                                                                                \
 150.817 +                        {                                                                                               \
 150.818 +                                vram[(addr) & 0x3fffff] = dest_dat;                              \
 150.819 +                                changedvram[((addr) & 0x3fffff) >> 10] = changeframecount;       \
 150.820 +                        }                                                                                               \
 150.821 +                        else if (s3_bpp == 1)                                                                           \
 150.822 +                        {                                                                                               \
 150.823 +                                vram_w[(addr) & 0x1fffff] = dest_dat;                            \
 150.824 +                                changedvram[((addr) & 0x1fffff) >> 9] = changeframecount;        \
 150.825 +                        }                                                                                               \
 150.826 +                        else                                                                                            \
 150.827 +                        {                                                                                               \
 150.828 +                                vram_l[(addr) & 0xfffff] = dest_dat;                             \
 150.829 +                                changedvram[((addr) & 0xfffff) >> 8] = changeframecount;         \
 150.830 +                        }
 150.831 +
 150.832 +void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat)
 150.833 +{
 150.834 +        uint32_t dest, destbak;
 150.835 +        int sx, sy, cx, cy;
 150.836 +        int x, y;
 150.837 +        uint32_t src_dat, dest_dat;
 150.838 +        int frgd_mix, bkgd_mix;
 150.839 +        int mix;
 150.840 +        int clip_t = s3_accel.multifunc[1] & 0xfff;
 150.841 +        int clip_l = s3_accel.multifunc[2] & 0xfff;
 150.842 +        int clip_b = s3_accel.multifunc[3] & 0xfff;
 150.843 +        int clip_r = s3_accel.multifunc[4] & 0xfff;
 150.844 +        int vram_mask = (s3_accel.multifunc[0xa] & 0xc0) == 0xc0;
 150.845 +        uint32_t mix_mask;
 150.846 +        uint16_t *vram_w = (uint16_t *)vram;
 150.847 +        uint32_t *vram_l = (uint32_t *)vram;
 150.848 +        uint32_t compare = s3_accel.color_cmp;
 150.849 +        int compare_mode = (s3_accel.multifunc[0xe] >> 7) & 3;
 150.850 +//return;
 150.851 +//        if (!cpu_input) pclog("Start S3 command %i  %i, %i  %i, %i (clip %i, %i to %i, %i  %i)\n", s3_accel.cmd >> 13, s3_accel.cur_x, s3_accel.cur_y, s3_accel.maj_axis_pcnt & 0xfff, s3_accel.multifunc[0]  & 0xfff, clip_l, clip_t, clip_r, clip_b, s3_accel.multifunc[0xe] & 0x20);
 150.852 +//        else            pclog("      S3 command %i, %i, %08x %08x\n", s3_accel.cmd >> 13, count, mix_dat, cpu_dat);
 150.853 +
 150.854 +        if (!cpu_input) s3_accel.dat_count = 0;
 150.855 +        if (cpu_input && (s3_accel.multifunc[0xa] & 0xc0) != 0x80)
 150.856 +        {
 150.857 +                if (s3_bpp == 3 && count == 2)
 150.858 +                {
 150.859 +                        if (s3_accel.dat_count)
 150.860 +                        {
 150.861 +                                cpu_dat = (cpu_dat & 0xffff) | (s3_accel.dat_buf << 16);
 150.862 +                                count = 4;
 150.863 +                                s3_accel.dat_count = 0;
 150.864 +                        }
 150.865 +                        else
 150.866 +                        {
 150.867 +                                s3_accel.dat_buf = cpu_dat & 0xffff;
 150.868 +                                s3_accel.dat_count = 1;
 150.869 +                        }
 150.870 +                }
 150.871 +                if (s3_bpp == 1) count >>= 1;
 150.872 +                if (s3_bpp == 3) count >>= 2;
 150.873 +        }
 150.874 +        
 150.875 +        switch (s3_accel.cmd & 0x600)
 150.876 +        {
 150.877 +                case 0x000: mix_mask = 0x80; break;
 150.878 +                case 0x200: mix_mask = 0x8000; break;
 150.879 +                case 0x400: mix_mask = 0x80000000; break;
 150.880 +                case 0x600: mix_mask = 0x80000000; break;
 150.881 +        }
 150.882 +
 150.883 +        if (s3_bpp == 0) compare &=   0xff;
 150.884 +        if (s3_bpp == 1) compare &= 0xffff;
 150.885 +        switch (s3_accel.cmd >> 13)
 150.886 +        {
 150.887 +                case 1: /*Draw line*/
 150.888 +                if (!cpu_input) /*!cpu_input is trigger to start operation*/
 150.889 +                {
 150.890 +                        s3_accel.cx   = s3_accel.cur_x;
 150.891 +                        if (s3_accel.cur_x & 0x1000) s3_accel.cx |= ~0xfff;
 150.892 +                        s3_accel.cy   = s3_accel.cur_y;
 150.893 +                        if (s3_accel.cur_y & 0x1000) s3_accel.cy |= ~0xfff;
 150.894 +                        
 150.895 +                        s3_accel.sy = s3_accel.maj_axis_pcnt;
 150.896 +                }
 150.897 +                if ((s3_accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
 150.898 +                if (s3_accel.cmd & 8) /*Radial*/
 150.899 +                {
 150.900 +                        while (count-- && s3_accel.sy >= 0)
 150.901 +                        {
 150.902 +                                if (s3_accel.cx >= clip_l && s3_accel.cx <= clip_r &&
 150.903 +                                    s3_accel.cy >= clip_t && s3_accel.cy <= clip_b)
 150.904 +                                {
 150.905 +                                        switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
 150.906 +                                        {
 150.907 +                                                case 0: src_dat = s3_accel.bkgd_color; break;
 150.908 +                                                case 1: src_dat = s3_accel.frgd_color; break;
 150.909 +                                                case 2: src_dat = cpu_dat; break;
 150.910 +                                                case 3: src_dat = 0; break;
 150.911 +                                        }
 150.912 +
 150.913 +                                        if ((compare_mode == 2 && src_dat != compare) ||
 150.914 +                                            (compare_mode == 3 && src_dat == compare) ||
 150.915 +                                             compare_mode < 2)
 150.916 +                                        {
 150.917 +                                                READ((s3_accel.cy * s3_width) + s3_accel.cx, dest_dat);
 150.918 +                                        
 150.919 +                                                MIX
 150.920 +
 150.921 +                                                WRITE((s3_accel.cy * s3_width) + s3_accel.cx);
 150.922 +                                        }
 150.923 +                                }
 150.924 +
 150.925 +                                mix_dat <<= 1;
 150.926 +                                mix_dat |= 1;
 150.927 +                                if (s3_bpp == 0) cpu_dat >>= 8;
 150.928 +                                else             cpu_dat >>= 16;
 150.929 +
 150.930 +                                switch (s3_accel.cmd & 0xe0)
 150.931 +                                {
 150.932 +                                        case 0x00: s3_accel.cx++;                break;
 150.933 +                                        case 0x20: s3_accel.cx++; s3_accel.cy--; break;
 150.934 +                                        case 0x40:                s3_accel.cy--; break;
 150.935 +                                        case 0x60: s3_accel.cx--; s3_accel.cy--; break;
 150.936 +                                        case 0x80: s3_accel.cx--;                break;
 150.937 +                                        case 0xa0: s3_accel.cx--; s3_accel.cy++; break;
 150.938 +                                        case 0xc0:                s3_accel.cy++; break;
 150.939 +                                        case 0xe0: s3_accel.cx++; s3_accel.cy++; break;
 150.940 +                                }
 150.941 +                                s3_accel.sy--;
 150.942 +                        }
 150.943 +                }
 150.944 +                else /*Bresenham*/
 150.945 +                {
 150.946 +                        while (count-- && s3_accel.sy >= 0)
 150.947 +                        {
 150.948 +                                if (s3_accel.cx >= clip_l && s3_accel.cx <= clip_r &&
 150.949 +                                    s3_accel.cy >= clip_t && s3_accel.cy <= clip_b)
 150.950 +                                {
 150.951 +                                        switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
 150.952 +                                        {
 150.953 +                                                case 0: src_dat = s3_accel.bkgd_color; break;
 150.954 +                                                case 1: src_dat = s3_accel.frgd_color; break;
 150.955 +                                                case 2: src_dat = cpu_dat; break;
 150.956 +                                                case 3: src_dat = 0; break;
 150.957 +                                        }
 150.958 +
 150.959 +                                        if ((compare_mode == 2 && src_dat != compare) ||
 150.960 +                                            (compare_mode == 3 && src_dat == compare) ||
 150.961 +                                             compare_mode < 2)
 150.962 +                                        {
 150.963 +                                                READ((s3_accel.cy * s3_width) + s3_accel.cx, dest_dat);
 150.964 +
 150.965 +//                                        pclog("Line : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X (%02X %02X)  ", s3_accel.cx, s3_accel.cy, s3_accel.dest + s3_accel.cx, src_dat, vram[s3_accel.src + s3_accel.cx], mix_dat & mix_mask, s3_accel.src + s3_accel.cx, dest_dat, s3_accel.frgd_color, s3_accel.bkgd_color);
 150.966 +                                        
 150.967 +                                                MIX
 150.968 +
 150.969 +//                                        pclog("%02X\n", dest_dat);
 150.970 +                                        
 150.971 +                                                WRITE((s3_accel.cy * s3_width) + s3_accel.cx);
 150.972 +                                        }
 150.973 +                                }
 150.974 +
 150.975 +                                mix_dat <<= 1;
 150.976 +                                mix_dat |= 1;
 150.977 +                                if (s3_bpp == 0) cpu_dat >>= 8;
 150.978 +                                else             cpu_dat >>= 16;
 150.979 +
 150.980 +//                                pclog("%i, %i - %i %i  %i %i\n", s3_accel.cx, s3_accel.cy, s3_accel.err_term, s3_accel.maj_axis_pcnt, s3_accel.desty_axstp, s3_accel.destx_distp);
 150.981 +
 150.982 +                                if (s3_accel.err_term >= s3_accel.maj_axis_pcnt)
 150.983 +                                {
 150.984 +                                        s3_accel.err_term += s3_accel.destx_distp;
 150.985 +                                        /*Step minor axis*/
 150.986 +                                        switch (s3_accel.cmd & 0xe0)
 150.987 +                                        {
 150.988 +                                                case 0x00: s3_accel.cy--; break;
 150.989 +                                                case 0x20: s3_accel.cy--; break;
 150.990 +                                                case 0x40: s3_accel.cx--; break;
 150.991 +                                                case 0x60: s3_accel.cx++; break;
 150.992 +                                                case 0x80: s3_accel.cy++; break;
 150.993 +                                                case 0xa0: s3_accel.cy++; break;
 150.994 +                                                case 0xc0: s3_accel.cx--; break;
 150.995 +                                                case 0xe0: s3_accel.cx++; break;
 150.996 +                                        }
 150.997 +                                }
 150.998 +                                else
 150.999 +                                   s3_accel.err_term += s3_accel.desty_axstp;
150.1000 +
150.1001 +                                /*Step major axis*/
150.1002 +                                switch (s3_accel.cmd & 0xe0)
150.1003 +                                {
150.1004 +                                        case 0x00: s3_accel.cx--; break;
150.1005 +                                        case 0x20: s3_accel.cx++; break;
150.1006 +                                        case 0x40: s3_accel.cy--; break;
150.1007 +                                        case 0x60: s3_accel.cy--; break;
150.1008 +                                        case 0x80: s3_accel.cx--; break;
150.1009 +                                        case 0xa0: s3_accel.cx++; break;
150.1010 +                                        case 0xc0: s3_accel.cy++; break;
150.1011 +                                        case 0xe0: s3_accel.cy++; break;
150.1012 +                                }
150.1013 +                                s3_accel.sy--;
150.1014 +                        }
150.1015 +                }
150.1016 +                break;
150.1017 +                
150.1018 +                case 2: /*Rectangle fill*/
150.1019 +                if (!cpu_input) /*!cpu_input is trigger to start operation*/
150.1020 +                {
150.1021 +                        s3_accel.sx   = s3_accel.maj_axis_pcnt & 0xfff;
150.1022 +                        s3_accel.sy   = s3_accel.multifunc[0]  & 0xfff;
150.1023 +                        s3_accel.cx   = s3_accel.cur_x;
150.1024 +                        if (s3_accel.cur_x & 0x1000) s3_accel.cx |= ~0xfff;
150.1025 +                        s3_accel.cy   = s3_accel.cur_y;
150.1026 +                        if (s3_accel.cur_y & 0x1000) s3_accel.cy |= ~0xfff;
150.1027 +                        
150.1028 +                        s3_accel.dest = s3_accel.cy * s3_width;
150.1029 +
150.1030 +//                        pclog("Dest %08X  (%i, %i) %04X %04X\n", s3_accel.dest, s3_accel.cx, s3_accel.cy, s3_accel.cur_x, s3_accel.cur_x & 0x1000);
150.1031 +                }
150.1032 +                if ((s3_accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
150.1033 +//                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
150.1034 +//                   return;
150.1035 +
150.1036 +                frgd_mix = (s3_accel.frgd_mix >> 5) & 3;
150.1037 +                bkgd_mix = (s3_accel.bkgd_mix >> 5) & 3;
150.1038 +                
150.1039 +                while (count-- && s3_accel.sy >= 0)
150.1040 +                {
150.1041 +                        if (s3_accel.cx >= clip_l && s3_accel.cx <= clip_r &&
150.1042 +                            s3_accel.cy >= clip_t && s3_accel.cy <= clip_b)
150.1043 +                        {
150.1044 +                                switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
150.1045 +                                {
150.1046 +                                        case 0: src_dat = s3_accel.bkgd_color; break;
150.1047 +                                        case 1: src_dat = s3_accel.frgd_color; break;
150.1048 +                                        case 2: src_dat = cpu_dat; break;
150.1049 +                                        case 3: src_dat = 0; break;
150.1050 +                                }
150.1051 +
150.1052 +                                if ((compare_mode == 2 && src_dat != compare) ||
150.1053 +                                    (compare_mode == 3 && src_dat == compare) ||
150.1054 +                                     compare_mode < 2)
150.1055 +                                {
150.1056 +                                        READ(s3_accel.dest + s3_accel.cx, dest_dat);
150.1057 +                                
150.1058 +//                                if (CS != 0xc000) pclog("Write %05X  %02X %02X  %04X (%02X %02X)  ", s3_accel.dest + s3_accel.cx, src_dat, dest_dat, mix_dat, s3_accel.frgd_mix, s3_accel.bkgd_mix);
150.1059 +
150.1060 +                                        MIX
150.1061 +                                
150.1062 +//                                if (CS != 0xc000) pclog("%02X\n", dest_dat);
150.1063 +                                
150.1064 +                                        WRITE(s3_accel.dest + s3_accel.cx);
150.1065 +                                }
150.1066 +                        }
150.1067 +                
150.1068 +                        mix_dat <<= 1;
150.1069 +                        mix_dat |= 1;
150.1070 +                        if (s3_bpp == 0) cpu_dat >>= 8;
150.1071 +                        else             cpu_dat >>= 16;
150.1072 +                        
150.1073 +                        if (s3_accel.cmd & 0x20) s3_accel.cx++;
150.1074 +                        else                     s3_accel.cx--;
150.1075 +                        s3_accel.sx--;
150.1076 +                        if (s3_accel.sx < 0)
150.1077 +                        {
150.1078 +                                if (s3_accel.cmd & 0x20) s3_accel.cx   -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1079 +                                else                     s3_accel.cx   += (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1080 +//                                s3_accel.dest -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1081 +                                s3_accel.sx    = s3_accel.maj_axis_pcnt & 0xfff;
150.1082 +                                
150.1083 +//                                s3_accel.dest  += s3_width;
150.1084 +                                if (s3_accel.cmd & 0x80) s3_accel.cy++;
150.1085 +                                else                     s3_accel.cy--;
150.1086 +                                
150.1087 +                                s3_accel.dest = s3_accel.cy * s3_width;
150.1088 +                                s3_accel.sy--;
150.1089 +
150.1090 +                                if (cpu_input/* && (s3_accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
150.1091 +                                if (s3_accel.sy < 0)
150.1092 +                                {
150.1093 +                                        return;
150.1094 +                                }
150.1095 +                        }
150.1096 +                }
150.1097 +                break;
150.1098 +
150.1099 +                case 6: /*BitBlt*/
150.1100 +                if (!cpu_input) /*!cpu_input is trigger to start operation*/
150.1101 +                {
150.1102 +                        s3_accel.sx   = s3_accel.maj_axis_pcnt & 0xfff;
150.1103 +                        s3_accel.sy   = s3_accel.multifunc[0]  & 0xfff;
150.1104 +
150.1105 +                        s3_accel.dx   = s3_accel.destx_distp & 0xfff;
150.1106 +                        if (s3_accel.destx_distp & 0x1000) s3_accel.dx |= ~0xfff;
150.1107 +                        s3_accel.dy   = s3_accel.desty_axstp & 0xfff;
150.1108 +                        if (s3_accel.desty_axstp & 0x1000) s3_accel.dy |= ~0xfff;
150.1109 +
150.1110 +                        s3_accel.cx   = s3_accel.cur_x & 0xfff;
150.1111 +                        if (s3_accel.cur_x & 0x1000) s3_accel.cx |= ~0xfff;
150.1112 +                        s3_accel.cy   = s3_accel.cur_y & 0xfff;
150.1113 +                        if (s3_accel.cur_y & 0x1000) s3_accel.cy |= ~0xfff;
150.1114 +
150.1115 +                        s3_accel.src  = s3_accel.cy * s3_width;
150.1116 +                        s3_accel.dest = s3_accel.dy * s3_width;
150.1117 +                        
150.1118 +//                        pclog("Source %08X Dest %08X  (%i, %i) - (%i, %i)\n", s3_accel.src, s3_accel.dest, s3_accel.cx, s3_accel.cy, s3_accel.dx, s3_accel.dy);
150.1119 +                }
150.1120 +                if ((s3_accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
150.1121 +//                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
150.1122 +//                  return;
150.1123 +
150.1124 +                if (s3_accel.sy < 0)
150.1125 +                   return;
150.1126 +
150.1127 +                frgd_mix = (s3_accel.frgd_mix >> 5) & 3;
150.1128 +                bkgd_mix = (s3_accel.bkgd_mix >> 5) & 3;
150.1129 +                
150.1130 +                if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode &&
150.1131 +                    (s3_accel.cmd & 0xa0) == 0xa0 && (s3_accel.frgd_mix & 0xf) == 7) 
150.1132 +                {
150.1133 +                        while (1)
150.1134 +                        {
150.1135 +                                if (s3_accel.dx >= clip_l && s3_accel.dx <= clip_r &&
150.1136 +                                    s3_accel.dy >= clip_t && s3_accel.dy <= clip_b)
150.1137 +                                {
150.1138 +                                        READ(s3_accel.src + s3_accel.cx, src_dat);
150.1139 +        
150.1140 +                                        dest_dat = src_dat;
150.1141 +                                        
150.1142 +                                        WRITE(s3_accel.dest + s3_accel.dx);
150.1143 +                                }
150.1144 +        
150.1145 +                                s3_accel.cx++;
150.1146 +                                s3_accel.dx++;
150.1147 +                                s3_accel.sx--;
150.1148 +                                if (s3_accel.sx < 0)
150.1149 +                                {
150.1150 +                                        s3_accel.cx -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1151 +                                        s3_accel.dx -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1152 +                                        s3_accel.sx  =  s3_accel.maj_axis_pcnt & 0xfff;
150.1153 +        
150.1154 +                                        s3_accel.cy++;
150.1155 +                                        s3_accel.dy++;
150.1156 +        
150.1157 +                                        s3_accel.src  = s3_accel.cy * s3_width;
150.1158 +                                        s3_accel.dest = s3_accel.dy * s3_width;
150.1159 +        
150.1160 +                                        s3_accel.sy--;
150.1161 +        
150.1162 +                                        if (s3_accel.sy < 0)
150.1163 +                                           return;
150.1164 +                                }
150.1165 +                        }
150.1166 +                }
150.1167 +                else
150.1168 +                {                     
150.1169 +                        while (count-- && s3_accel.sy >= 0)
150.1170 +                        {
150.1171 +                                if (s3_accel.dx >= clip_l && s3_accel.dx <= clip_r &&
150.1172 +                                    s3_accel.dy >= clip_t && s3_accel.dy <= clip_b)
150.1173 +                                {
150.1174 +                                        if (vram_mask)
150.1175 +                                        {
150.1176 +                                                READ(s3_accel.src + s3_accel.cx, mix_dat)
150.1177 +                                                mix_dat = mix_dat ? mix_mask : 0;
150.1178 +                                        }
150.1179 +                                        switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
150.1180 +                                        {
150.1181 +                                                case 0: src_dat = s3_accel.bkgd_color;                  break;
150.1182 +                                                case 1: src_dat = s3_accel.frgd_color;                  break;
150.1183 +                                                case 2: src_dat = cpu_dat;                              break;
150.1184 +                                                case 3: READ(s3_accel.src + s3_accel.cx, src_dat);      break;
150.1185 +                                        }
150.1186 +
150.1187 +                                        if ((compare_mode == 2 && src_dat != compare) ||
150.1188 +                                            (compare_mode == 3 && src_dat == compare) ||
150.1189 +                                             compare_mode < 2)
150.1190 +                                        {
150.1191 +                                                READ(s3_accel.dest + s3_accel.dx, dest_dat);
150.1192 +                                                                                
150.1193 +//                                pclog("BitBlt : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X   ", s3_accel.dx, s3_accel.dy, s3_accel.dest + s3_accel.dx, src_dat, vram[s3_accel.src + s3_accel.cx], mix_dat, s3_accel.src + s3_accel.cx, dest_dat);
150.1194 +                                
150.1195 +                                                MIX
150.1196 +
150.1197 +//                                pclog("%02X\n", dest_dat);
150.1198 +
150.1199 +                                                WRITE(s3_accel.dest + s3_accel.dx);
150.1200 +                                        }
150.1201 +                                }
150.1202 +
150.1203 +                                mix_dat <<= 1;
150.1204 +                                mix_dat |= 1;
150.1205 +                                if (s3_bpp == 0) cpu_dat >>= 8;
150.1206 +                                else             cpu_dat >>= 16;
150.1207 +
150.1208 +                                if (s3_accel.cmd & 0x20)
150.1209 +                                {
150.1210 +                                        s3_accel.cx++;
150.1211 +                                        s3_accel.dx++;
150.1212 +                                }
150.1213 +                                else
150.1214 +                                {
150.1215 +                                        s3_accel.cx--;
150.1216 +                                        s3_accel.dx--;
150.1217 +                                }
150.1218 +                                s3_accel.sx--;
150.1219 +                                if (s3_accel.sx < 0)
150.1220 +                                {
150.1221 +                                        if (s3_accel.cmd & 0x20)
150.1222 +                                        {
150.1223 +                                                s3_accel.cx -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1224 +                                                s3_accel.dx -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1225 +                                        }
150.1226 +                                        else
150.1227 +                                        {
150.1228 +                                                s3_accel.cx += (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1229 +                                                s3_accel.dx += (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1230 +                                        }
150.1231 +                                        s3_accel.sx    =  s3_accel.maj_axis_pcnt & 0xfff;
150.1232 +
150.1233 +                                        if (s3_accel.cmd & 0x80)
150.1234 +                                        {
150.1235 +                                                s3_accel.cy++;
150.1236 +                                                s3_accel.dy++;
150.1237 +                                        }
150.1238 +                                        else
150.1239 +                                        {
150.1240 +                                                s3_accel.cy--;
150.1241 +                                                s3_accel.dy--;
150.1242 +                                        }
150.1243 +
150.1244 +                                        s3_accel.src  = s3_accel.cy * s3_width;
150.1245 +                                        s3_accel.dest = s3_accel.dy * s3_width;
150.1246 +
150.1247 +                                        s3_accel.sy--;
150.1248 +
150.1249 +                                        if (cpu_input/* && (s3_accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
150.1250 +                                        if (s3_accel.sy < 0)
150.1251 +                                        {
150.1252 +                                                return;
150.1253 +                                        }
150.1254 +                                }
150.1255 +                        }
150.1256 +                }
150.1257 +                break;
150.1258 +
150.1259 +                case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/
150.1260 +                if (!cpu_input) /*!cpu_input is trigger to start operation*/
150.1261 +                {
150.1262 +                        s3_accel.sx   = s3_accel.maj_axis_pcnt & 0xfff;
150.1263 +                        s3_accel.sy   = s3_accel.multifunc[0]  & 0xfff;
150.1264 +
150.1265 +                        s3_accel.dx   = s3_accel.destx_distp & 0xfff;
150.1266 +                        if (s3_accel.destx_distp & 0x1000) s3_accel.dx |= ~0xfff;
150.1267 +                        s3_accel.dy   = s3_accel.desty_axstp & 0xfff;
150.1268 +                        if (s3_accel.desty_axstp & 0x1000) s3_accel.dy |= ~0xfff;
150.1269 +
150.1270 +                        s3_accel.cx   = s3_accel.cur_x & 0xfff;
150.1271 +                        if (s3_accel.cur_x & 0x1000) s3_accel.cx |= ~0xfff;
150.1272 +                        s3_accel.cy   = s3_accel.cur_y & 0xfff;
150.1273 +                        if (s3_accel.cur_y & 0x1000) s3_accel.cy |= ~0xfff;
150.1274 +                        
150.1275 +                        /*Align source with destination*/
150.1276 +//                        s3_accel.cx = (s3_accel.cx & ~7) | (s3_accel.dx & 7);
150.1277 +//                        s3_accel.cy = (s3_accel.cy & ~7) | (s3_accel.dy & 7);
150.1278 +
150.1279 +                        s3_accel.pattern  = (s3_accel.cy * s3_width) + s3_accel.cx;
150.1280 +                        s3_accel.dest     = s3_accel.dy * s3_width;
150.1281 +                        
150.1282 +                        s3_accel.cx = s3_accel.dx & 7;
150.1283 +                        s3_accel.cy = s3_accel.dy & 7;
150.1284 +                        
150.1285 +                        s3_accel.src  = s3_accel.pattern + (s3_accel.cy * s3_width);
150.1286 +
150.1287 +//                        pclog("Source %08X Dest %08X  (%i, %i) - (%i, %i)\n", s3_accel.src, s3_accel.dest, s3_accel.cx, s3_accel.cy, s3_accel.dx, s3_accel.dy);
150.1288 +//                        dumpregs();
150.1289 +//                        exit(-1);
150.1290 +                }
150.1291 +                if ((s3_accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
150.1292 +//                if ((s3_accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
150.1293 +//                   return;
150.1294 +
150.1295 +                frgd_mix = (s3_accel.frgd_mix >> 5) & 3;
150.1296 +                bkgd_mix = (s3_accel.bkgd_mix >> 5) & 3;
150.1297 +
150.1298 +                while (count-- && s3_accel.sy >= 0)
150.1299 +                {
150.1300 +                        if (s3_accel.dx >= clip_l && s3_accel.dx <= clip_r &&
150.1301 +                            s3_accel.dy >= clip_t && s3_accel.dy <= clip_b)
150.1302 +                        {
150.1303 +                                if (vram_mask)
150.1304 +                                {
150.1305 +                                        READ(s3_accel.src + s3_accel.cx, mix_dat)
150.1306 +                                        mix_dat = mix_dat ? mix_mask : 0;
150.1307 +                                }
150.1308 +                                switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
150.1309 +                                {
150.1310 +                                        case 0: src_dat = s3_accel.bkgd_color;                  break;
150.1311 +                                        case 1: src_dat = s3_accel.frgd_color;                  break;
150.1312 +                                        case 2: src_dat = cpu_dat;                              break;
150.1313 +                                        case 3: READ(s3_accel.src + s3_accel.cx, src_dat);      break;
150.1314 +                                }
150.1315 +
150.1316 +                                if ((compare_mode == 2 && src_dat != compare) ||
150.1317 +                                    (compare_mode == 3 && src_dat == compare) ||
150.1318 +                                     compare_mode < 2)
150.1319 +                                {
150.1320 +                                        READ(s3_accel.dest + s3_accel.dx, dest_dat);
150.1321 +                                
150.1322 +//                                pclog("Pattern fill : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X   ", s3_accel.dx, s3_accel.dy, s3_accel.dest + s3_accel.dx, src_dat, vram[s3_accel.src + s3_accel.cx], mix_dat, s3_accel.src + s3_accel.cx, dest_dat);
150.1323 +
150.1324 +                                        MIX
150.1325 +
150.1326 +//                                pclog("%02X\n", dest_dat);
150.1327 +
150.1328 +                                        WRITE(s3_accel.dest + s3_accel.dx);
150.1329 +                                }
150.1330 +                        }
150.1331 +
150.1332 +                        mix_dat <<= 1;
150.1333 +                        mix_dat |= 1;
150.1334 +                        if (s3_bpp == 0) cpu_dat >>= 8;
150.1335 +                        else             cpu_dat >>= 16;
150.1336 +
150.1337 +                        if (s3_accel.cmd & 0x20)
150.1338 +                        {
150.1339 +                                s3_accel.cx = ((s3_accel.cx + 1) & 7) | (s3_accel.cx & ~7);
150.1340 +                                s3_accel.dx++;
150.1341 +                        }
150.1342 +                        else
150.1343 +                        {
150.1344 +                                s3_accel.cx = ((s3_accel.cx - 1) & 7) | (s3_accel.cx & ~7);
150.1345 +                                s3_accel.dx--;
150.1346 +                        }
150.1347 +                        s3_accel.sx--;
150.1348 +                        if (s3_accel.sx < 0)
150.1349 +                        {
150.1350 +                                if (s3_accel.cmd & 0x20)
150.1351 +                                {
150.1352 +                                        s3_accel.cx = ((s3_accel.cx - ((s3_accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3_accel.cx & ~7);
150.1353 +                                        s3_accel.dx -= (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1354 +                                }
150.1355 +                                else
150.1356 +                                {
150.1357 +                                        s3_accel.cx = ((s3_accel.cx + ((s3_accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3_accel.cx & ~7);
150.1358 +                                        s3_accel.dx += (s3_accel.maj_axis_pcnt & 0xfff) + 1;
150.1359 +                                }
150.1360 +                                s3_accel.sx    =  s3_accel.maj_axis_pcnt & 0xfff;
150.1361 +
150.1362 +                                if (s3_accel.cmd & 0x80)
150.1363 +                                {
150.1364 +                                        s3_accel.cy = ((s3_accel.cy + 1) & 7) | (s3_accel.cy & ~7);
150.1365 +                                        s3_accel.dy++;
150.1366 +                                }
150.1367 +                                else
150.1368 +                                {
150.1369 +                                        s3_accel.cy = ((s3_accel.cy - 1) & 7) | (s3_accel.cy & ~7);
150.1370 +                                        s3_accel.dy--;
150.1371 +                                }
150.1372 +
150.1373 +                                s3_accel.src  = s3_accel.pattern + (s3_accel.cy * s3_width);
150.1374 +                                s3_accel.dest = s3_accel.dy * s3_width;
150.1375 +
150.1376 +                                s3_accel.sy--;
150.1377 +
150.1378 +                                if (cpu_input/* && (s3_accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
150.1379 +                                if (s3_accel.sy < 0)
150.1380 +                                {
150.1381 +                                        return;
150.1382 +                                }
150.1383 +                        }
150.1384 +                }
150.1385 +                break;
150.1386 +        }
150.1387 +}
150.1388 +
150.1389 +void s3_hwcursor_draw(int displine)
150.1390 +{
150.1391 +        int x;
150.1392 +        uint16_t dat[2];
150.1393 +        int xx;
150.1394 +        int offset = svga_hwcursor_latch.x - svga_hwcursor_latch.xoff;
150.1395 +        
150.1396 +        for (x = 0; x < 64; x += 16)
150.1397 +        {
150.1398 +                dat[0] = (vram[svga_hwcursor_latch.addr]     << 8) | vram[svga_hwcursor_latch.addr + 1];
150.1399 +                dat[1] = (vram[svga_hwcursor_latch.addr + 2] << 8) | vram[svga_hwcursor_latch.addr + 3];
150.1400 +                for (xx = 0; xx < 16; xx++)
150.1401 +                {
150.1402 +                        if (offset >= svga_hwcursor_latch.x)
150.1403 +                        {
150.1404 +                                if (!(dat[0] & 0x8000))
150.1405 +                                   ((uint32_t *)buffer32->line[displine])[offset + 32]  = (dat[1] & 0x8000) ? 0xffffff : 0;
150.1406 +                                else if (dat[1] & 0x8000)
150.1407 +                                   ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
150.1408 +//                                pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
150.1409 +                        }
150.1410 +                           
150.1411 +                        offset++;
150.1412 +                        dat[0] <<= 1;
150.1413 +                        dat[1] <<= 1;
150.1414 +                }
150.1415 +                svga_hwcursor_latch.addr += 4;
150.1416 +        }
150.1417 +}
150.1418 +
150.1419 +
150.1420 +uint8_t s3_pci_read(int func, int addr)
150.1421 +{
150.1422 +        pclog("S3 PCI read %08X\n", addr);
150.1423 +        switch (addr)
150.1424 +        {
150.1425 +                case 0x00: return 0x33; /*'S3'*/
150.1426 +                case 0x01: return 0x53;
150.1427 +                
150.1428 +                case 0x02: return s3_id_ext;
150.1429 +                case 0x03: return 0x88;
150.1430 +                
150.1431 +                case 0x04: return 0x03; /*Respond to IO and memory accesses*/
150.1432 +
150.1433 +                case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
150.1434 +                
150.1435 +                case 0x08: return 0; /*Revision ID*/
150.1436 +                case 0x09: return 0; /*Programming interface*/
150.1437 +                
150.1438 +                case 0x0a: return 0x01; /*Supports VGA interface*/
150.1439 +                case 0x0b: return 0x03;
150.1440 +                
150.1441 +                case 0x10: return 0x00; /*Linear frame buffer address*/
150.1442 +                case 0x11: return 0x00;
150.1443 +                case 0x12: return crtc[0x5a] & 0x80;
150.1444 +                case 0x13: return crtc[0x59];
150.1445 +
150.1446 +                case 0x30: return 0x01; /*BIOS ROM address*/
150.1447 +                case 0x31: return 0x00;
150.1448 +                case 0x32: return 0x0C;
150.1449 +                case 0x33: return 0x00;
150.1450 +        }
150.1451 +        return 0;
150.1452 +}
150.1453 +
150.1454 +void s3_pci_write(int func, int addr, uint8_t val)
150.1455 +{
150.1456 +        switch (addr)
150.1457 +        {
150.1458 +                case 0x12: crtc[0x5a] = val & 0x80; s3_updatemapping(); break;
150.1459 +                case 0x13: crtc[0x59] = val;        s3_updatemapping(); break;                
150.1460 +        }
150.1461 +}
150.1462 +
150.1463 +int s3_init()
150.1464 +{
150.1465 +        if (gfxcard == GFX_BAHAMAS64)
150.1466 +        {
150.1467 +                s3_id = 0xc1; /*Vision864P*/
150.1468 +                s3_id_ext = 0xc1; /*Trio64*/
150.1469 +        }
150.1470 +        if (gfxcard == GFX_N9_9FX)
150.1471 +        {
150.1472 +                s3_id = 0xe1;
150.1473 +                s3_id_ext = 0x11; /*Trio64*/
150.1474 +        }
150.1475 +        if (gfxcard == GFX_STEALTH64)
150.1476 +        {
150.1477 +                s3_id = 0xe1; /*Trio64*/
150.1478 +                s3_id_ext = 0x11;
150.1479 +        }
150.1480 +        svga_recalctimings_ex = s3_recalctimings;
150.1481 +        svga_hwcursor_draw    = s3_hwcursor_draw;
150.1482 +
150.1483 +        crtc[0x36] = 1 | (2 << 2) | (1 << 4) | (4 << 5);
150.1484 +        crtc[0x37] = 1 | (7 << 5);
150.1485 +        
150.1486 +        vrammask = 0x3fffff;
150.1487 +
150.1488 +        io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1489 +        io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1490 +        io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1491 +        io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1492 +        io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1493 +        io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1494 +        io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1495 +        io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1496 +        io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1497 +        io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1498 +        io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1499 +        io_sethandler(0xa2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1500 +        io_sethandler(0xa6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1501 +        io_sethandler(0xaae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1502 +        io_sethandler(0xaee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1503 +        io_sethandler(0xb2e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1504 +        io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1505 +        io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1506 +        io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL);
150.1507 +        io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l);
150.1508 +
150.1509 +        pci_add(s3_pci_read, s3_pci_write);
150.1510 + 
150.1511 +        svga_vram_limit = 4 << 20; /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/
150.1512 +        return svga_init();
150.1513 +}
150.1514 +
150.1515 +GFXCARD vid_s3 =
150.1516 +{
150.1517 +        s3_init,
150.1518 +        /*IO at 3Cx/3Dx*/
150.1519 +        s3_out,
150.1520 +        s3_in,
150.1521 +        /*IO at 3Ax/3Bx*/
150.1522 +        video_out_null,
150.1523 +        video_in_null,
150.1524 +
150.1525 +        svga_poll,
150.1526 +        svga_recalctimings,
150.1527 +
150.1528 +        svga_write,
150.1529 +        video_write_null,
150.1530 +        video_write_null,
150.1531 +
150.1532 +        svga_read,
150.1533 +        video_read_null,
150.1534 +        video_read_null
150.1535 +};
150.1536 +
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/src/vid_sdac_ramdac.c	Sun Apr 21 14:54:35 2013 +0100
   151.3 @@ -0,0 +1,148 @@
   151.4 +/*87C716 'SDAC' true colour RAMDAC emulation*/
   151.5 +/*Misidentifies as AT&T 21C504*/
   151.6 +#include "ibm.h"
   151.7 +#include "video.h"
   151.8 +#include "vid_svga.h"
   151.9 +#include "vid_sdac_ramdac.h"
  151.10 +
  151.11 +struct
  151.12 +{
  151.13 +        int magic_count;
  151.14 +        uint8_t command;
  151.15 +        int windex, rindex;
  151.16 +        uint16_t regs[256];
  151.17 +        int reg_ff;
  151.18 +        int rs2;
  151.19 +} sdac_ramdac;
  151.20 +
  151.21 +void sdac_ramdac_out(uint16_t addr, uint8_t val)
  151.22 +{
  151.23 +        int didwrite;
  151.24 +//        /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X  %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2);
  151.25 +        switch (addr)
  151.26 +        {
  151.27 +                case 0x3C6:
  151.28 +                if (val == 0xff)
  151.29 +                {
  151.30 +                        sdac_ramdac.rs2 = 0;
  151.31 +                        sdac_ramdac.magic_count = 0;
  151.32 +                        break;
  151.33 +                }
  151.34 +                if (sdac_ramdac.magic_count < 4) break;
  151.35 +                if (sdac_ramdac.magic_count == 4)
  151.36 +                {
  151.37 +                        sdac_ramdac.command = val;
  151.38 +//                        pclog("RAMDAC command reg now %02X\n", val);
  151.39 +                        switch (val >> 4)
  151.40 +                        {
  151.41 +                                case 2: case 3: case 0xa: bpp = 15; break;
  151.42 +                                case 4: case 0xe: bpp = 24; break;
  151.43 +                                case 5: case 6: case 0xc: bpp = 16; break;
  151.44 +                                case 7: bpp = 32; break;
  151.45 +
  151.46 +                                case 0: case 1: default: bpp = 8; break;
  151.47 +                        }
  151.48 +                }
  151.49 +                //sdac_ramdac.magic_count = 0;
  151.50 +                break;
  151.51 +                
  151.52 +                case 0x3C7:
  151.53 +                sdac_ramdac.magic_count = 0;
  151.54 +                if (sdac_ramdac.rs2)
  151.55 +                   sdac_ramdac.rindex = val;
  151.56 +                break;
  151.57 +                case 0x3C8:
  151.58 +                sdac_ramdac.magic_count = 0;
  151.59 +                if (sdac_ramdac.rs2)
  151.60 +                   sdac_ramdac.windex = val;
  151.61 +                break;
  151.62 +                case 0x3C9:
  151.63 +                sdac_ramdac.magic_count = 0;
  151.64 +                if (sdac_ramdac.rs2)
  151.65 +                {
  151.66 +                        if (!sdac_ramdac.reg_ff) sdac_ramdac.regs[sdac_ramdac.windex] = (sdac_ramdac.regs[sdac_ramdac.windex] & 0xff00) | val;
  151.67 +                        else                    sdac_ramdac.regs[sdac_ramdac.windex] = (sdac_ramdac.regs[sdac_ramdac.windex] & 0x00ff) | (val << 8);
  151.68 +                        sdac_ramdac.reg_ff = !sdac_ramdac.reg_ff;
  151.69 +//                        pclog("RAMDAC reg %02X now %04X\n", sdac_ramdac.windex, sdac_ramdac.regs[sdac_ramdac.windex]);
  151.70 +                        if (!sdac_ramdac.reg_ff) sdac_ramdac.windex++;
  151.71 +                }
  151.72 +                break;
  151.73 +        }
  151.74 +        svga_out(addr,val);
  151.75 +}
  151.76 +
  151.77 +uint8_t sdac_ramdac_in(uint16_t addr)
  151.78 +{
  151.79 +        uint8_t temp;
  151.80 +//        /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, sdac_ramdac.rs2);
  151.81 +        switch (addr)
  151.82 +        {
  151.83 +                case 0x3C6:
  151.84 +                sdac_ramdac.reg_ff = 0;
  151.85 +                if (sdac_ramdac.magic_count < 5)
  151.86 +                   sdac_ramdac.magic_count++;
  151.87 +                if (sdac_ramdac.magic_count == 4)
  151.88 +                {
  151.89 +                        temp = 0x70; /*SDAC ID*/
  151.90 +                        sdac_ramdac.rs2 = 1;
  151.91 +                }
  151.92 +                if (sdac_ramdac.magic_count == 5)
  151.93 +                {
  151.94 +                        temp = sdac_ramdac.command;
  151.95 +                        sdac_ramdac.magic_count = 0;
  151.96 +                }
  151.97 +                return temp;
  151.98 +                case 0x3C7:
  151.99 +//                if (sdac_ramdac.magic_count < 4)
 151.100 +//                {
 151.101 +                        sdac_ramdac.magic_count=0;
 151.102 +//                        break;
 151.103 +//                }
 151.104 +                if (sdac_ramdac.rs2) return sdac_ramdac.rindex;
 151.105 +                break;
 151.106 +                case 0x3C8:
 151.107 +//                if (sdac_ramdac.magic_count < 4)
 151.108 +//                {
 151.109 +                        sdac_ramdac.magic_count=0;
 151.110 +//                        break;
 151.111 +//                }
 151.112 +                if (sdac_ramdac.rs2) return sdac_ramdac.windex;
 151.113 +                break;
 151.114 +                case 0x3C9:
 151.115 +//                if (sdac_ramdac.magic_count < 4)
 151.116 +//                {
 151.117 +                        sdac_ramdac.magic_count=0;
 151.118 +//                        break;
 151.119 +//                }
 151.120 +                if (sdac_ramdac.rs2)
 151.121 +                {
 151.122 +                        if (!sdac_ramdac.reg_ff) temp = sdac_ramdac.regs[sdac_ramdac.rindex] & 0xff;
 151.123 +                        else                     temp = sdac_ramdac.regs[sdac_ramdac.rindex] >> 8;
 151.124 +                        sdac_ramdac.reg_ff = !sdac_ramdac.reg_ff;
 151.125 +                        if (!sdac_ramdac.reg_ff)
 151.126 +                        {
 151.127 +                                sdac_ramdac.rindex++;
 151.128 +                                sdac_ramdac.magic_count = 0;
 151.129 +                        }
 151.130 +                        return temp;
 151.131 +                }
 151.132 +                break;
 151.133 +        }
 151.134 +        return svga_in(addr);
 151.135 +}
 151.136 +
 151.137 +float sdac_getclock(int clock)
 151.138 +{
 151.139 +        float t;
 151.140 +        int m, n1, n2;
 151.141 +//        pclog("SDAC_Getclock %i %04X\n", clock, sdac_ramdac.regs[clock]);
 151.142 +        if (clock == 0) return 25175000.0;
 151.143 +        if (clock == 1) return 28322000.0;
 151.144 +        clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
 151.145 +        m  =  (sdac_ramdac.regs[clock] & 0x7f) + 2;
 151.146 +        n1 = ((sdac_ramdac.regs[clock] >>  8) & 0x1f) + 2;
 151.147 +        n2 = ((sdac_ramdac.regs[clock] >> 13) & 0x07);
 151.148 +        t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
 151.149 +//        pclog("SDAC clock %i %i %i %f %04X  %f %i\n", m, n1, n2, t, sdac_ramdac.regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2);
 151.150 +        return t;
 151.151 +}
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/src/vid_sdac_ramdac.h	Sun Apr 21 14:54:35 2013 +0100
   152.3 @@ -0,0 +1,4 @@
   152.4 +void sdac_ramdac_out(uint16_t addr, uint8_t val);
   152.5 +uint8_t sdac_ramdac_in(uint16_t addr);
   152.6 +
   152.7 +float sdac_getclock(int clock);
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/src/vid_stg_ramdac.c	Sun Apr 21 14:54:35 2013 +0100
   153.3 @@ -0,0 +1,104 @@
   153.4 +/*STG1702 true colour RAMDAC emulation*/
   153.5 +#include "ibm.h"
   153.6 +#include "video.h"
   153.7 +#include "vid_svga.h"
   153.8 +#include "vid_stg_ramdac.h"
   153.9 +
  153.10 +struct
  153.11 +{
  153.12 +        int magic_count;
  153.13 +        uint8_t command;
  153.14 +        int index;
  153.15 +        uint8_t regs[256];
  153.16 +} stg_ramdac;
  153.17 +
  153.18 +int stg_state_read[2][8]={{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
  153.19 +int stg_state_write[8]={0,0,0,0,0,6,7,7};
  153.20 +
  153.21 +void stg_ramdac_out(uint16_t addr, uint8_t val)
  153.22 +{
  153.23 +        int didwrite;
  153.24 +        //if (CS!=0xC000) pclog("OUT RAMDAC %04X %02X %i %04X:%04X\n",addr,val,stg_ramdac.magic_count,CS,pc);
  153.25 +        switch (addr)
  153.26 +        {
  153.27 +                case 0x3C6:
  153.28 +                switch (stg_ramdac.magic_count)
  153.29 +                {
  153.30 +                        case 0: case 1: case 2: case 3: break;
  153.31 +                        case 4: stg_ramdac.command=val; /*pclog("Write RAMDAC command %02X\n",val);*/ break;
  153.32 +                        case 5: stg_ramdac.index=(stg_ramdac.index&0xFF00)|val; break;
  153.33 +                        case 6: stg_ramdac.index=(stg_ramdac.index&0xFF)|(val<<8); break;
  153.34 +                        case 7:
  153.35 +                                pclog("Write RAMDAC reg %02X %02X\n", stg_ramdac.index, val);
  153.36 +                        if (stg_ramdac.index<0x100) stg_ramdac.regs[stg_ramdac.index]=val;
  153.37 +                        stg_ramdac.index++;
  153.38 +                        break;
  153.39 +                }
  153.40 +                didwrite = (stg_ramdac.magic_count>=4);
  153.41 +                stg_ramdac.magic_count=stg_state_write[stg_ramdac.magic_count&7];
  153.42 +                if (stg_ramdac.command&8)
  153.43 +                {
  153.44 +                        switch (stg_ramdac.regs[3])
  153.45 +                        {
  153.46 +                                case 0: case 5: case 7: bpp=8; break;
  153.47 +                                case 1: case 2: case 8: bpp=15; break;
  153.48 +                                case 3: case 6: bpp=16; break;
  153.49 +                                case 4: case 9: bpp=24; break;
  153.50 +                                default: bpp=8; break;
  153.51 +                        }
  153.52 +                }
  153.53 +                else
  153.54 +                {
  153.55 +                        switch (stg_ramdac.command>>5)
  153.56 +                        {
  153.57 +                                case 0: bpp=8;  break;
  153.58 +                                case 5: bpp=15; break;
  153.59 +                                case 6: bpp=16; break;
  153.60 +                                case 7: bpp=24; break;
  153.61 +                                default: bpp=8; break;
  153.62 +                        }
  153.63 +                }
  153.64 +                if (didwrite) return;
  153.65 +                break;
  153.66 +                case 0x3C7: case 0x3C8: case 0x3C9:
  153.67 +                stg_ramdac.magic_count=0;
  153.68 +                break;
  153.69 +        }
  153.70 +        svga_out(addr,val);
  153.71 +}
  153.72 +
  153.73 +uint8_t stg_ramdac_in(uint16_t addr)
  153.74 +{
  153.75 +        uint8_t temp;
  153.76 +        //if (CS!=0xC000) pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
  153.77 +        switch (addr)
  153.78 +        {
  153.79 +                case 0x3C6:
  153.80 +                switch (stg_ramdac.magic_count)
  153.81 +                {
  153.82 +                        case 0: case 1: case 2: case 3: temp=0xFF; break;
  153.83 +                        case 4: temp=stg_ramdac.command; break;
  153.84 +                        case 5: temp=stg_ramdac.index&0xFF; break;
  153.85 +                        case 6: temp=stg_ramdac.index>>8; break;
  153.86 +                        case 7:
  153.87 +//                                pclog("Read RAMDAC index %04X\n",stg_ramdac.index);
  153.88 +                        switch (stg_ramdac.index)
  153.89 +                        {
  153.90 +                                case 0: temp=0x44; break;
  153.91 +                                case 1: temp=0x02; break;
  153.92 +                                default:
  153.93 +                                if (stg_ramdac.index<0x100) temp=stg_ramdac.regs[stg_ramdac.index];
  153.94 +                                else                        temp=0xFF;
  153.95 +                                break;
  153.96 +                        }
  153.97 +                        stg_ramdac.index++;
  153.98 +                        break;
  153.99 +                }
 153.100 +                stg_ramdac.magic_count=stg_state_read[(stg_ramdac.command&0x10)?1:0][stg_ramdac.magic_count&7];
 153.101 +                return temp;
 153.102 +                case 0x3C8: case 0x3C9:
 153.103 +                stg_ramdac.magic_count=0;
 153.104 +                break;
 153.105 +        }
 153.106 +        return svga_in(addr);
 153.107 +}
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/src/vid_stg_ramdac.h	Sun Apr 21 14:54:35 2013 +0100
   154.3 @@ -0,0 +1,2 @@
   154.4 +void stg_ramdac_out(uint16_t addr, uint8_t val);
   154.5 +uint8_t stg_ramdac_in(uint16_t addr);
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/src/vid_svga.c	Sun Apr 21 14:54:35 2013 +0100
   155.3 @@ -0,0 +1,1392 @@
   155.4 +/*Generic SVGA handling*/
   155.5 +/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
   155.6 +#include "ibm.h"
   155.7 +#include "video.h"
   155.8 +#include "vid_svga.h"
   155.9 +#include "io.h"
  155.10 +
  155.11 +uint32_t svga_vram_limit;
  155.12 +
  155.13 +extern uint8_t edatlookup[4][4];
  155.14 +uint8_t svga_miscout;
  155.15 +
  155.16 +static uint8_t la, lb, lc, ld;
  155.17 +static uint8_t svga_rotate[8][256];
  155.18 +
  155.19 +static int svga_fast;
  155.20 +
  155.21 +void svga_out(uint16_t addr, uint8_t val)
  155.22 +{
  155.23 +        int c;
  155.24 +        uint8_t o;
  155.25 +        //printf("OUT SVGA %03X %02X %04X:%04X %i %08X\n",addr,val,CS,pc,TRIDENT,svgawbank);
  155.26 +        switch (addr)
  155.27 +        {
  155.28 +                case 0x3C0:
  155.29 +                if (!attrff)
  155.30 +                   attraddr=val&31;
  155.31 +                else
  155.32 +                {
  155.33 +                        attrregs[attraddr&31]=val;
  155.34 +                        if (attraddr<16) fullchange=changeframecount;
  155.35 +                        if (attraddr==0x10 || attraddr==0x14 || attraddr<0x10)
  155.36 +                        {
  155.37 +                                for (c=0;c<16;c++)
  155.38 +                                {
  155.39 +                                        if (attrregs[0x10]&0x80) egapal[c]=(attrregs[c]&0xF)|((attrregs[0x14]&0xF)<<4);
  155.40 +                                        else                     egapal[c]=(attrregs[c]&0x3F)|((attrregs[0x14]&0xC)<<4);
  155.41 +                                }
  155.42 +                        }
  155.43 +                        if (attraddr == 0x10) svga_recalctimings();
  155.44 +                }
  155.45 +                attrff^=1;
  155.46 +                break;
  155.47 +                case 0x3C2:
  155.48 +                svga_miscout = val;
  155.49 +                vres = 0; pallook = pallook256;
  155.50 +                vidclock = val & 4; printf("3C2 write %02X\n",val);
  155.51 +                if (val&1)
  155.52 +                   io_sethandler(0x03a0, 0x0020, video_in,      NULL, NULL, video_out,      NULL, NULL);
  155.53 +                else
  155.54 +                   io_sethandler(0x03a0, 0x0020, video_in_null, NULL, NULL, video_out_null, NULL, NULL);
  155.55 +                break;
  155.56 +                case 0x3C4: seqaddr=val; break;
  155.57 +                case 0x3C5:
  155.58 +                if (seqaddr > 0xf) return;
  155.59 +                o=seqregs[seqaddr&0xF];
  155.60 +                seqregs[seqaddr&0xF]=val;
  155.61 +                if (o!=val && (seqaddr&0xF)==1) svga_recalctimings();
  155.62 +                switch (seqaddr&0xF)
  155.63 +                {
  155.64 +                        case 1: if (scrblank && !(val&0x20)) fullchange=3; scrblank=(scrblank&~0x20)|(val&0x20); break;
  155.65 +                        case 2: writemask=val&0xF; break;
  155.66 +                        case 3:
  155.67 +                        charset=val&0xF;
  155.68 +                        charseta=((charset>>2)*0x10000)+2;
  155.69 +                        charsetb=((charset&3) *0x10000)+2;
  155.70 +                        break;
  155.71 +                        case 4: 
  155.72 +                        chain4=val&8; /*printf("Chain4 %i %02X\n",val&8,gdcreg[5]&0x60); */
  155.73 +                        svga_fast = (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1]) && chain4;
  155.74 +                        break;
  155.75 +                }
  155.76 +                break;
  155.77 +                case 0x3C7: dacread=val; dacpos=0; break;
  155.78 +                case 0x3C8: dacwrite=val; dacpos=0; break;
  155.79 +                case 0x3C9:
  155.80 +                palchange=1;
  155.81 +                fullchange=changeframecount;
  155.82 +                switch (dacpos)
  155.83 +                {
  155.84 +                        case 0: vgapal[dacwrite].r=val&63; pallook256[dacwrite]=makecol32(vgapal[dacwrite].r*4,vgapal[dacwrite].g*4,vgapal[dacwrite].b*4); dacpos++; break;
  155.85 +                        case 1: vgapal[dacwrite].g=val&63; pallook256[dacwrite]=makecol32(vgapal[dacwrite].r*4,vgapal[dacwrite].g*4,vgapal[dacwrite].b*4); dacpos++; break;
  155.86 +                        case 2: vgapal[dacwrite].b=val&63; pallook256[dacwrite]=makecol32(vgapal[dacwrite].r*4,vgapal[dacwrite].g*4,vgapal[dacwrite].b*4); dacpos=0; dacwrite=(dacwrite+1)&255; break;
  155.87 +                }
  155.88 +                break;
  155.89 +                case 0x3CE: gdcaddr=val; break;
  155.90 +                case 0x3CF:
  155.91 +                switch (gdcaddr&15)
  155.92 +                {
  155.93 +                        case 2: colourcompare=val; break;
  155.94 +                        case 4: readplane=val&3; break;
  155.95 +                        case 5: writemode=val&3; readmode=val&8; break;
  155.96 +                        case 6:
  155.97 +                        if ((gdcreg[6] & 0xc) != (val & 0xc))
  155.98 +                        {
  155.99 +                                mem_removehandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 155.100 +//                                pclog("Write mapping %02X\n", val);
 155.101 +                                switch (val&0xC)
 155.102 +                                {
 155.103 +                                        case 0x0: /*128k at A0000*/
 155.104 +                                        mem_sethandler(0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 155.105 +                                        break;
 155.106 +                                        case 0x4: /*64k at A0000*/
 155.107 +                                        mem_sethandler(0xa0000, 0x10000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 155.108 +                                        break;
 155.109 +                                        case 0x8: /*32k at B0000*/
 155.110 +                                        mem_sethandler(0xb0000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 155.111 +                                        break;
 155.112 +                                        case 0xC: /*32k at B8000*/
 155.113 +                                        mem_sethandler(0xb8000, 0x08000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
 155.114 +                                        break;
 155.115 +                                }
 155.116 +                        }
 155.117 +                        break;
 155.118 +                        case 7: colournocare=val; break;
 155.119 +                }
 155.120 +                gdcreg[gdcaddr&15]=val;                
 155.121 +                svga_fast = (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1]) && chain4;
 155.122 +                break;
 155.123 +        }
 155.124 +}
 155.125 +
 155.126 +uint8_t svga_in(uint16_t addr)
 155.127 +{
 155.128 +        uint8_t temp;
 155.129 +//        if (addr!=0x3da) pclog("Read port %04X\n",addr);
 155.130 +        switch (addr)
 155.131 +        {
 155.132 +                case 0x3C0: return attraddr;
 155.133 +                case 0x3C1: return attrregs[attraddr];
 155.134 +                case 0x3C2: return 0x10;
 155.135 +                case 0x3C4: return seqaddr;
 155.136 +                case 0x3C5:
 155.137 +                return seqregs[seqaddr&0xF];
 155.138 +                case 0x3C8: return dacwrite;
 155.139 +                case 0x3C9:
 155.140 +                palchange=1;
 155.141 +                switch (dacpos)
 155.142 +                {
 155.143 +                        case 0: dacpos++; return vgapal[dacread].r;
 155.144 +                        case 1: dacpos++; return vgapal[dacread].g;
 155.145 +                        case 2: dacpos=0; dacread=(dacread+1)&255; return vgapal[(dacread-1)&255].b;
 155.146 +                }
 155.147 +                break;
 155.148 +                case 0x3CC: return svga_miscout;
 155.149 +                case 0x3CE: return gdcaddr;
 155.150 +                case 0x3CF:
 155.151 +                return gdcreg[gdcaddr&0xF];
 155.152 +                case 0x3DA:
 155.153 +                attrff=0;
 155.154 +                cgastat^=0x30;
 155.155 +                return cgastat;
 155.156 +        }
 155.157 +//        printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
 155.158 +        return 0xFF;
 155.159 +}
 155.160 +
 155.161 +int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split;
 155.162 +int svga_hdisp,  svga_htotal,  svga_rowoffset;
 155.163 +int svga_lowres, svga_interlace;
 155.164 +double svga_clock;
 155.165 +uint32_t svga_ma;
 155.166 +void (*svga_recalctimings_ex)() = NULL;
 155.167 +void (*svga_hwcursor_draw)(int displine) = NULL;
 155.168 +
 155.169 +void svga_recalctimings()
 155.170 +{
 155.171 +        double crtcconst;
 155.172 +        int temp;
 155.173 +        svga_vtotal=crtc[6];
 155.174 +        svga_dispend=crtc[0x12];
 155.175 +        svga_vsyncstart=crtc[0x10];
 155.176 +        svga_split=crtc[0x18];
 155.177 +
 155.178 +        if (crtc[7]&1)    svga_vtotal|=0x100;
 155.179 +        if (crtc[7]&32)   svga_vtotal|=0x200;
 155.180 +        svga_vtotal+=2;
 155.181 +
 155.182 +
 155.183 +        if (crtc[7]&2)    svga_dispend|=0x100;
 155.184 +        if (crtc[7]&64)   svga_dispend|=0x200;
 155.185 +        svga_dispend++;
 155.186 +
 155.187 +        if (crtc[7]&4)    svga_vsyncstart|=0x100;
 155.188 +        if (crtc[7]&128)  svga_vsyncstart|=0x200;
 155.189 +        svga_vsyncstart++;
 155.190 +
 155.191 +        if (crtc[7]&0x10) svga_split|=0x100;
 155.192 +        if (crtc[9]&0x40) svga_split|=0x200;
 155.193 +        svga_split++;
 155.194 +
 155.195 +        svga_hdisp=crtc[1];
 155.196 +        svga_hdisp++;
 155.197 +
 155.198 +        svga_htotal=crtc[0];
 155.199 +        svga_htotal+=6; /*+6 is required for Tyrian*/
 155.200 +
 155.201 +        svga_rowoffset=crtc[0x13];
 155.202 +
 155.203 +        svga_clock = (vidclock) ? VGACONST2 : VGACONST1;
 155.204 +        
 155.205 +        svga_lowres = attrregs[0x10]&0x40;
 155.206 +        
 155.207 +        svga_interlace = 0;
 155.208 +        
 155.209 +        svga_ma = (crtc[0xC]<<8)|crtc[0xD];
 155.210 +        
 155.211 +        if (svga_recalctimings_ex) svga_recalctimings_ex();
 155.212 +        
 155.213 +        crtcconst=(seqregs[1]&1)?(svga_clock*8.0):(svga_clock*9.0);
 155.214 +
 155.215 +        disptime  =svga_htotal;
 155.216 +        dispontime=svga_hdisp;
 155.217 +
 155.218 +//        printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
 155.219 +        if (seqregs[1]&8) { disptime*=2; dispontime*=2; }
 155.220 +        dispofftime=disptime-dispontime;
 155.221 +        dispontime*=crtcconst;
 155.222 +        dispofftime*=crtcconst;
 155.223 +
 155.224 +//        printf("SVGA horiz total %i display end %i clock rate %i vidclock %i %i\n",crtc[0],crtc[1],egaswitchread,vidclock,((ega3c2>>2)&3) | ((tridentnewctrl2<<2)&4));
 155.225 +//        printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga_vtotal,svga_dispend,(crtc[9]&31)+1,svga_vsyncstart);
 155.226 +//        printf("total %f on %f cycles off %f cycles frame %f sec %f %02X\n",disptime*crtcconst,dispontime,dispofftime,(dispontime+dispofftime)*svga_vtotal,(dispontime+dispofftime)*svga_vtotal*70,seqregs[1]);
 155.227 +}
 155.228 +
 155.229 +
 155.230 +static uint32_t ma,maback,ca;
 155.231 +static int vc,sc;
 155.232 +static int linepos, displine, vslines, linecountff, oddeven;
 155.233 +static int svga_dispon;
 155.234 +static int con, coff, cursoron, cgablink;
 155.235 +static int scrollcache;
 155.236 +
 155.237 +int svga_hwcursor_on;
 155.238 +
 155.239 +SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch;
 155.240 +
 155.241 +int svga_hdisp_on;
 155.242 +
 155.243 +static int firstline_draw = 2000, lastline_draw = 0;
 155.244 +
 155.245 +void svga_poll()
 155.246 +{
 155.247 +        uint8_t chr,dat,attr;
 155.248 +        uint32_t charaddr;
 155.249 +        int x,xx;
 155.250 +        uint32_t fg,bg;
 155.251 +        int offset;
 155.252 +        uint8_t edat[4];
 155.253 +        int drawcursor=0;
 155.254 +        if (!linepos)
 155.255 +        {
 155.256 +//                if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
 155.257 +                if (displine == svga_hwcursor_latch.y && svga_hwcursor_latch.ena)
 155.258 +                   svga_hwcursor_on = 64 - svga_hwcursor_latch.yoff;
 155.259 +                vidtime+=dispofftime;
 155.260 +//                if (output) printf("Display off %f\n",vidtime);
 155.261 +                cgastat|=1;
 155.262 +                linepos=1;
 155.263 +
 155.264 +                if (svga_dispon)
 155.265 +                {
 155.266 +                        svga_hdisp_on=1;
 155.267 +                        
 155.268 +                        ma&=vrammask;
 155.269 +                        if (firstline==2000) firstline=displine;
 155.270 +                        if (scrblank)
 155.271 +                        {
 155.272 +                                if (firstline_draw == 2000) firstline_draw = displine;
 155.273 +                                lastline_draw = displine;
 155.274 +                                for (x=0;x<svga_hdisp;x++)
 155.275 +                                {
 155.276 +                                        switch (seqregs[1]&9)
 155.277 +                                        {
 155.278 +                                                case 0:
 155.279 +                                                for (xx=0;xx<9;xx++) ((uint32_t *)buffer32->line[displine])[(x*9)+xx+32]=0;
 155.280 +                                                break;
 155.281 +                                                case 1:
 155.282 +                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[(x*8)+xx+32]=0;
 155.283 +                                                break;
 155.284 +                                                case 8:
 155.285 +                                                for (xx=0;xx<18;xx++) ((uint32_t *)buffer32->line[displine])[(x*18)+xx+32]=0;
 155.286 +                                                break;
 155.287 +                                                case 9:
 155.288 +                                                for (xx=0;xx<16;xx++) ((uint32_t *)buffer32->line[displine])[(x*16)+xx+32]=0;
 155.289 +                                                break;
 155.290 +                                        }
 155.291 +                                }
 155.292 +                        }
 155.293 +                        else if (!(gdcreg[6]&1)) /*Text mode*/
 155.294 +                        {
 155.295 +                                if (firstline_draw == 2000) firstline_draw = displine;
 155.296 +                                lastline_draw = displine;
 155.297 +                                if (fullchange)
 155.298 +                                {
 155.299 +                                        for (x=0;x<svga_hdisp;x++)
 155.300 +                                        {
 155.301 +                                                drawcursor=((ma==ca) && con && cursoron);
 155.302 +                                                chr=vram[(ma<<1)];
 155.303 +                                                attr=vram[(ma<<1)+4];
 155.304 +                                                if (attr&8) charaddr=charsetb+(chr*128);
 155.305 +                                                else        charaddr=charseta+(chr*128);
 155.306 +
 155.307 +                                                if (drawcursor) { bg=pallook[egapal[attr&15]]; fg=pallook[egapal[attr>>4]]; }
 155.308 +                                                else
 155.309 +                                                {
 155.310 +                                                        fg=pallook[egapal[attr&15]];
 155.311 +                                                        bg=pallook[egapal[attr>>4]];
 155.312 +                                                        if (attr&0x80 && attrregs[0x10]&8)
 155.313 +                                                        {
 155.314 +                                                                bg=pallook[egapal[(attr>>4)&7]];
 155.315 +                                                                if (cgablink&16) fg=bg;
 155.316 +                                                        }
 155.317 +                                                }
 155.318 +
 155.319 +                                                dat=vram[charaddr+(sc<<2)];
 155.320 +                                                if (seqregs[1]&8) /*40 column*/
 155.321 +                                                {
 155.322 +                                                        if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<4)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x<<4)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg; }
 155.323 +                                                        else
 155.324 +                                                        {
 155.325 +                                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*18)+32+(xx<<1))&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+33+(xx<<1))&2047]=(dat&(0x80>>xx))?fg:bg;
 155.326 +                                                                if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=bg;
 155.327 +                                                                else                  ((uint32_t *)buffer32->line[displine])[((x*18)+32+16)&2047]=((uint32_t *)buffer32->line[displine])[((x*18)+32+17)&2047]=(dat&1)?fg:bg;
 155.328 +                                                        }
 155.329 +                                                }
 155.330 +                                                else             /*80 column*/
 155.331 +                                                {
 155.332 +                                                        if (seqregs[1]&1) { for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x<<3)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg; }
 155.333 +                                                        else
 155.334 +                                                        {
 155.335 +                                                                for (xx=0;xx<8;xx++) ((uint32_t *)buffer32->line[displine])[((x*9)+32+xx)&2047]=(dat&(0x80>>xx))?fg:bg;
 155.336 +                                                                if ((chr&~0x1F)!=0xC0 || !(attrregs[0x10]&4)) ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=bg;
 155.337 +                                                                else                  ((uint32_t *)buffer32->line[displine])[((x*9)+32+8)&2047]=(dat&1)?fg:bg;
 155.338 +                                                        }
 155.339 +                                                }
 155.340 +                                                ma+=4; ma&=vrammask;
 155.341 +                                        }
 155.342 +                                }
 155.343 +                        }
 155.344 +                        else
 155.345 +                        {
 155.346 +//                                if (hwcursor_on) changedvram[ma>>10]=changedvram[(ma>>10)+1]=2;
 155.347 +                                switch (gdcreg[5]&0x60)
 155.348 +                                {
 155.349 +                                        case 0x00: /*16 colours*/
 155.350 +                                        if (firstline_draw == 2000) firstline_draw = displine;
 155.351 +                                        lastline_draw = displine;
 155.352 +                                        if (seqregs[1]&8) /*Low res (320)*/
 155.353 +                                        {
 155.354 +                                                offset=((8-scrollcache)<<1)+16;
 155.355 +                                                for (x=0;x<=svga_hdisp;x++)
 155.356 +                                                {
 155.357 +                                                        edat[0]=vram[ma];
 155.358 +                                                        edat[1]=vram[ma|0x1];
 155.359 +                                                        edat[2]=vram[ma|0x2];
 155.360 +                                                        edat[3]=vram[ma|0x3];
 155.361 +                                                        ma+=4; ma&=vrammask;
 155.362 +
 155.363 +                                                        dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
 155.364 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[dat&0xF]];
 155.365 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[dat>>4]];
 155.366 +                                                        dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 155.367 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[dat&0xF]];
 155.368 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[dat>>4]];
 155.369 +                                                        dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 155.370 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[dat&0xF]];
 155.371 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[dat>>4]];
 155.372 +                                                        dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 155.373 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[dat&0xF]];
 155.374 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]=   ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[dat>>4]];
 155.375 +                                                }
 155.376 +                                        }
 155.377 +                                        else              /*High res (640)*/
 155.378 +                                        {
 155.379 +                                                offset=(8-scrollcache)+24;
 155.380 +                                                for (x=0;x<=svga_hdisp;x++)
 155.381 +                                                {
 155.382 +                                                        edat[0]=vram[ma];
 155.383 +                                                        edat[1]=vram[ma|0x1];
 155.384 +                                                        edat[2]=vram[ma|0x2];
 155.385 +                                                        edat[3]=vram[ma|0x3];
 155.386 +                                                        ma+=4; ma&=vrammask;
 155.387 +
 155.388 +                                                        dat=edatlookup[edat[0]&3][edat[1]&3]|(edatlookup[edat[2]&3][edat[3]&3]<<2);
 155.389 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[egapal[dat&0xF]];
 155.390 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]=pallook[egapal[dat>>4]];
 155.391 +                                                        dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 155.392 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[egapal[dat&0xF]];
 155.393 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]=pallook[egapal[dat>>4]];
 155.394 +                                                        dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 155.395 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[egapal[dat&0xF]];
 155.396 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]=pallook[egapal[dat>>4]];
 155.397 +                                                        dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 155.398 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[egapal[dat&0xF]];
 155.399 +                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+offset]=  pallook[egapal[dat>>4]];
 155.400 +                                                }
 155.401 +                                        }
 155.402 +                                        break;
 155.403 +                                        case 0x20: /*4 colours*/
 155.404 +                                        if (firstline_draw == 2000) firstline_draw = displine;
 155.405 +                                        lastline_draw = displine;
 155.406 +                                        offset=((8-scrollcache)<<1)+16;
 155.407 +                                        /*Low res (320) only, though high res (640) should be possible*/
 155.408 +                                        for (x=0;x<=svga_hdisp;x++)
 155.409 +                                        {
 155.410 +                                                if (sc&1 && !(crtc[0x17]&1))
 155.411 +                                                {
 155.412 +                                                        edat[0]=vram[(ma<<1)+0x8000];
 155.413 +                                                        edat[1]=vram[(ma<<1)+0x8004];
 155.414 +                                                }
 155.415 +                                                else
 155.416 +                                                {
 155.417 +                                                        edat[0]=vram[(ma<<1)];
 155.418 +                                                        edat[1]=vram[(ma<<1)+4];
 155.419 +                                                }
 155.420 +                                                ma+=4; ma&=vrammask;
 155.421 +
 155.422 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+14+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+15+offset]=pallook[egapal[edat[1]&3]];
 155.423 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+12+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+13+offset]=pallook[egapal[(edat[1]>>2)&3]];
 155.424 +                                                dat=edatlookup[(edat[0]>>2)&3][(edat[1]>>2)&3]|(edatlookup[(edat[2]>>2)&3][(edat[3]>>2)&3]<<2);
 155.425 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+10+offset]=((uint32_t *)buffer32->line[displine])[(x<<4)+11+offset]=pallook[egapal[(edat[1]>>4)&3]];
 155.426 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+8+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+9+offset]=pallook[egapal[(edat[1]>>6)&3]];
 155.427 +                                                dat=edatlookup[(edat[0]>>4)&3][(edat[1]>>4)&3]|(edatlookup[(edat[2]>>4)&3][(edat[3]>>4)&3]<<2);
 155.428 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+7+offset]=pallook[egapal[(edat[0]>>0)&3]];
 155.429 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+5+offset]=pallook[egapal[(edat[0]>>2)&3]];
 155.430 +                                                dat=edatlookup[edat[0]>>6][edat[1]>>6]|(edatlookup[edat[2]>>6][edat[3]>>6]<<2);
 155.431 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<4)+3+offset]=pallook[egapal[(edat[0]>>4)&3]];
 155.432 +                                                ((uint32_t *)buffer32->line[displine])[(x<<4)+offset]=   ((uint32_t *)buffer32->line[displine])[(x<<4)+1+offset]=pallook[egapal[(edat[0]>>6)&3]];
 155.433 +                                        }
 155.434 +                                        break;
 155.435 +                                        case 0x40: case 0x60: /*256 colours (and more, with high/true colour RAMDAC)*/
 155.436 +                                        if (changedvram[ma>>10] || changedvram[(ma>>10)+1] || changedvram[(ma>>10)+2] || fullchange)
 155.437 +                                        {
 155.438 +                                                if (firstline_draw == 2000) firstline_draw = displine;
 155.439 +                                                lastline_draw = displine;
 155.440 +                                                if (svga_lowres) /*Low res (320)*/
 155.441 +                                                {
 155.442 +//                                                        if (!displine) pclog("Lo res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3);
 155.443 +                                                        offset=(8-(scrollcache&6))+24;
 155.444 +                                                        if (bpp==8)   /*Regular 8 bpp palette mode*/
 155.445 +                                                        {
 155.446 +                                                                for (x=0;x<=svga_hdisp;x++)
 155.447 +                                                                {
 155.448 +                                                                        edat[0]=vram[ma];
 155.449 +                                                                        edat[1]=vram[ma|0x1];
 155.450 +                                                                        edat[2]=vram[ma|0x2];
 155.451 +                                                                        edat[3]=vram[ma|0x3];
 155.452 +                                                                        ma+=4; ma&=vrammask;
 155.453 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+6+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+7+offset]=pallook[edat[3]];
 155.454 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+4+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+5+offset]=pallook[edat[2]];
 155.455 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+2+offset]= ((uint32_t *)buffer32->line[displine])[(x<<3)+3+offset]=pallook[edat[1]];
 155.456 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<3)+offset]=   ((uint32_t *)buffer32->line[displine])[(x<<3)+1+offset]=pallook[edat[0]];
 155.457 +                                                                }
 155.458 +                                                        }
 155.459 +                                                        else if (bpp==16) /*16 bpp 565 mode*/
 155.460 +                                                        {
 155.461 +                                                                for (x=0;x<=svga_hdisp;x++)
 155.462 +                                                                {
 155.463 +                                                                        fg=vram[ma]|(vram[ma|0x1]<<8);
 155.464 +                                                                        bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
 155.465 +                                                                        ma+=4; ma&=vrammask;
 155.466 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
 155.467 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
 155.468 +                                                                }
 155.469 +                                                        }
 155.470 +                                                        else if (bpp==15) /*15 bpp 555 mode*/
 155.471 +                                                        {
 155.472 +                                                                for (x=0;x<=svga_hdisp;x++)
 155.473 +                                                                {
 155.474 +                                                                        fg=vram[ma]|(vram[ma|0x1]<<8);
 155.475 +                                                                        bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
 155.476 +                                                                        ma+=4; ma&=vrammask;
 155.477 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+2+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
 155.478 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
 155.479 +                                                                }
 155.480 +                                                        }
 155.481 +                                                        else if (bpp==24) /*24 bpp 888 mode*/
 155.482 +                                                        {
 155.483 +                                                                for (x=0;x<=((svga_hdisp<<3)/3);x++)
 155.484 +                                                                {
 155.485 +                                                                        fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
 155.486 +                                                                        ma+=3; ma&=vrammask;
 155.487 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+offset]=((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=fg;
 155.488 +                                                                }
 155.489 +                                                        }
 155.490 +                                                        else if (bpp==32) /*32 bpp 8888 mode*/
 155.491 +                                                        {
 155.492 +                                                                for (x = 0; x <= svga_hdisp; x++)
 155.493 +                                                                {
 155.494 +                                                                        fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16);
 155.495 +                                                                        ma += 4; ma &= vrammask;
 155.496 +                                                                        ((uint32_t *)buffer32->line[displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[displine])[(x << 1) + 1 + offset] = fg;
 155.497 +                                                                }
 155.498 +                                                        }
 155.499 +                                                }
 155.500 +                                                else    /*High res (SVGA only)*/
 155.501 +                                                {
 155.502 +//                                                        if (!displine) pclog("Hi res %i %i %i\n",bpp,svga_hdisp,(svga_hdisp<<3)/3);
 155.503 +                                                        offset=(8-((scrollcache&6)>>1))+24;
 155.504 +                                                        if (bpp==8)
 155.505 +                                                        {
 155.506 +                                                                for (x=0;x<=(svga_hdisp<<1);x++)
 155.507 +                                                                {
 155.508 +                                                                        edat[0]=vram[ma];
 155.509 +                                                                        edat[1]=vram[ma|0x1];
 155.510 +                                                                        edat[2]=vram[ma|0x2];
 155.511 +                                                                        edat[3]=vram[ma|0x3];
 155.512 +                                                                        ma+=4; ma&=vrammask;
 155.513 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+3+offset]=pallook[edat[3]];
 155.514 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+2+offset]=pallook[edat[2]];
 155.515 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+1+offset]=pallook[edat[1]];
 155.516 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<2)+offset]=  pallook[edat[0]];
 155.517 +                                                                }
 155.518 +                                                        }
 155.519 +                                                        else if (bpp==16)
 155.520 +                                                        {
 155.521 +                                                                for (x=0;x<=(svga_hdisp<<1);x++)
 155.522 +                                                                {
 155.523 +                                                                        fg=vram[ma]|(vram[ma|0x1]<<8);
 155.524 +                                                                        bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
 155.525 +                                                                        ma+=4; ma&=vrammask;
 155.526 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&63)<<10)|(((bg>>11)&31)<<19);
 155.527 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&63)<<10)|(((fg>>11)&31)<<19);
 155.528 +                                                                }
 155.529 +                                                        }
 155.530 +                                                        else if (bpp==15)
 155.531 +                                                        {
 155.532 +                                                                for (x=0;x<=(svga_hdisp<<1);x++)
 155.533 +                                                                {
 155.534 +                                                                        fg=vram[ma]|(vram[ma|0x1]<<8);
 155.535 +                                                                        bg=vram[ma|0x2]|(vram[ma|0x3]<<8);
 155.536 +                                                                        ma+=4; ma&=vrammask;
 155.537 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+1+offset]=((bg&31)<<3)|(((bg>>5)&31)<<11)|(((bg>>10)&31)<<19);
 155.538 +                                                                        ((uint32_t *)buffer32->line[displine])[(x<<1)+0+offset]=((fg&31)<<3)|(((fg>>5)&31)<<11)|(((fg>>10)&31)<<19);
 155.539 +                                                                }
 155.540 +                                                        }
 155.541 +                                                        else if (bpp==24)
 155.542 +                                                        {
 155.543 +                                                                for (x=0;x<=((svga_hdisp<<3)/3);x++)
 155.544 +                                                                {
 155.545 +                                                                        fg=vram[ma]|(vram[ma+1]<<8)|(vram[ma+2]<<16);
 155.546 +                                                                        ma+=3; ma&=vrammask;
 155.547 +                                                                        ((uint32_t *)buffer32->line[displine])[x+offset]=fg;
 155.548 +                                                                }
 155.549 +                                                        }
 155.550 +                                                        else if (bpp==32)
 155.551 +                                                        {
 155.552 +                                                                for (x = 0; x <= (svga_hdisp<<2); x++)
 155.553 +                                                                {
 155.554 +                                                                        fg = vram[ma] | (vram[ma + 1] << 8) | (vram[ma + 2] << 16);
 155.555 +                                                                        ma += 4; ma &= vrammask;
 155.556 +                                                                        ((uint32_t *)buffer32->line[displine])[x + offset] = fg;
 155.557 +                                                                }
 155.558 +                                                        }
 155.559 +                                                }
 155.560 +                                        }
 155.561 +                                        break;
 155.562 +                                }
 155.563 +                                if (svga_hwcursor_on)
 155.564 +                                {
 155.565 +                                        svga_hwcursor_draw(displine);
 155.566 +                                        svga_hwcursor_on--;
 155.567 +                                }
 155.568 +                        }
 155.569 +                        if (lastline<displine) lastline=displine;
 155.570 +                }
 155.571 +
 155.572 +//                pclog("%03i %06X %06X\n",displine,ma,vrammask);
 155.573 +                displine++;
 155.574 +                if (svga_interlace) displine++;
 155.575 +                if ((cgastat&8) && ((displine&15)==(crtc[0x11]&15)) && vslines)
 155.576 +                {
 155.577 +//                        printf("Vsync off at line %i\n",displine);
 155.578 +                        cgastat&=~8;
 155.579 +                }
 155.580 +                vslines++;
 155.581 +                if (displine>1500) displine=0;
 155.582 +//                pclog("Col is %08X %08X %08X   %i %i  %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322],
 155.583 +//                                                                displine, vc, ma);
 155.584 +        }
 155.585 +        else
 155.586 +        {
 155.587 +//                pclog("VC %i ma %05X\n", vc, ma);
 155.588 +                vidtime+=dispontime;
 155.589 +                
 155.590 +//                if (output) printf("Display on %f\n",vidtime);
 155.591 +                if (svga_dispon) cgastat&=~1;
 155.592 +                svga_hdisp_on=0;
 155.593 +                
 155.594 +                linepos=0;
 155.595 +                if (sc==(crtc[11]&31)) con = 0;
 155.596 +                if (svga_dispon)
 155.597 +                {
 155.598 +                        if ((crtc[9]&0x80) && !linecountff)
 155.599 +                        {
 155.600 +                                linecountff=1;
 155.601 +                                ma=maback;
 155.602 +                        }
 155.603 +                        else if (sc==(crtc[9]&31))
 155.604 +                        {
 155.605 +                                linecountff=0;
 155.606 +                                sc=0;
 155.607 +
 155.608 +                                maback += (svga_rowoffset<<3);
 155.609 +                                if (svga_interlace) maback += (svga_rowoffset<<3);
 155.610 +                                maback&=vrammask;
 155.611 +                                ma=maback;
 155.612 +                        }
 155.613 +                        else
 155.614 +                        {
 155.615 +                                linecountff=0;
 155.616 +                                sc++;
 155.617 +                                sc&=31;
 155.618 +                                ma=maback;
 155.619 +                        }
 155.620 +                }
 155.621 +                vc++;
 155.622 +                vc&=2047;
 155.623 +
 155.624 +                if (vc==svga_split)
 155.625 +                {
 155.626 +//                        pclog("VC split\n");
 155.627 +                        ma=maback=0;
 155.628 +                        if (attrregs[0x10]&0x20) scrollcache=0;
 155.629 +                }
 155.630 +                if (vc==svga_dispend)
 155.631 +                {
 155.632 +//                        pclog("VC dispend\n");
 155.633 +                        svga_dispon=0;
 155.634 +                        if (crtc[10] & 0x20) cursoron=0;
 155.635 +                        else                 cursoron=cgablink&16;
 155.636 +                        if (!(gdcreg[6]&1) && !(cgablink&15)) fullchange=2;
 155.637 +                        cgablink++;
 155.638 +
 155.639 +                        for (x=0;x<2048;x++) if (changedvram[x]) changedvram[x]--;
 155.640 +//                        memset(changedvram,0,2048);
 155.641 +                        if (fullchange) fullchange--;
 155.642 +                }
 155.643 +                if (vc==svga_vsyncstart)
 155.644 +                {
 155.645 +//                        pclog("VC vsync  %i %i\n", firstline_draw, lastline_draw);
 155.646 +                        svga_dispon=0;
 155.647 +                        cgastat|=8;
 155.648 +                        if (seqregs[1]&8) x=svga_hdisp*((seqregs[1]&1)?8:9)*2;
 155.649 +                        else              x=svga_hdisp*((seqregs[1]&1)?8:9);
 155.650 +
 155.651 +                        if (bpp == 16 || bpp == 15) x /= 2;
 155.652 +                        if (bpp == 24)              x /= 3;
 155.653 +                        if (bpp == 32)              x /= 4;
 155.654 +                        if (svga_interlace && !oddeven) lastline++;
 155.655 +                        if (svga_interlace &&  oddeven) firstline--;
 155.656 +
 155.657 +                        wx=x;
 155.658 +                        wy=lastline-firstline;
 155.659 +
 155.660 +
 155.661 +                        svga_doblit(firstline_draw, lastline_draw + 1);
 155.662 +
 155.663 +                        readflash=0;
 155.664 +
 155.665 +                        firstline=2000;
 155.666 +                        lastline=0;
 155.667 +                        
 155.668 +                        firstline_draw = 2000;
 155.669 +                        lastline_draw = 0;
 155.670 +                        
 155.671 +                        oddeven^=1;
 155.672 +
 155.673 +                        changeframecount=(svga_interlace)?3:2;
 155.674 +                        vslines=0;
 155.675 +                        
 155.676 +                        if (svga_interlace && oddeven) ma = maback = svga_ma + (svga_rowoffset << 1);
 155.677 +                        else                           ma = maback = svga_ma;
 155.678 +                        ca=(crtc[0xE]<<8)|crtc[0xF];
 155.679 +
 155.680 +                        ma <<= 2;
 155.681 +                        maback <<= 2;
 155.682 +                        ca <<= 2;
 155.683 +
 155.684 +
 155.685 +                        video_res_x = wx;
 155.686 +                        video_res_y = wy + 1;
 155.687 +                        
 155.688 +                        if (!(gdcreg[6]&1)) /*Text mode*/
 155.689 +                        {
 155.690 +                                video_res_x /= (seqregs[1] & 1) ? 8 : 9;
 155.691 +                                video_res_y /= (crtc[9] & 31) + 1;
 155.692 +                                video_bpp = 0;
 155.693 +                        }
 155.694 +                        else
 155.695 +                        {
 155.696 +                                if (crtc[9] & 0x80)
 155.697 +                                   video_res_y /= 2;
 155.698 +                                if (!(crtc[0x17] & 1))
 155.699 +                                   video_res_y *= 2;
 155.700 +                                video_res_y /= (crtc[9] & 31) + 1;                                   
 155.701 +                                if ((seqregs[1] & 8) || svga_lowres)
 155.702 +                                   video_res_x /= 2;
 155.703 +                                switch (gdcreg[5]&0x60)
 155.704 +                                {
 155.705 +                                        case 0x00:            video_bpp = 4;   break;
 155.706 +                                        case 0x20:            video_bpp = 2;   break;
 155.707 +                                        case 0x40: case 0x60: video_bpp = bpp; break;
 155.708 +                                }
 155.709 +                        }
 155.710 +
 155.711 +//                        if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
 155.712 +                        
 155.713 +//                        pclog("Addr %08X vson %03X vsoff %01X  %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven);
 155.714 +                }
 155.715 +                if (vc==svga_vtotal)
 155.716 +                {
 155.717 +//                        pclog("VC vtotal\n");
 155.718 +
 155.719 +
 155.720 +//                        printf("Frame over at line %i %i  %i %i\n",displine,vc,svga_vsyncstart,svga_dispend);
 155.721 +                        vc=0;
 155.722 +                        sc=0;
 155.723 +                        svga_dispon=1;
 155.724 +                        displine=(svga_interlace && oddeven) ? 1 : 0; //(TRIDENT && (crtc[0x1E]&4) && oddeven)?1:0;
 155.725 +                        scrollcache=attrregs[0x13]&7;
 155.726 +                        linecountff=0;
 155.727 +                        
 155.728 +                        svga_hwcursor_on=0;
 155.729 +                        svga_hwcursor_latch = svga_hwcursor;
 155.730 +//                        pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
 155.731 +                        
 155.732 +//                        pclog("ADDR %08X\n",hwcursor_addr);
 155.733 +                }
 155.734 +                if (sc==(crtc[10]&31)) con=1;
 155.735 +        }
 155.736 +//        printf("2 %i\n",svga_vsyncstart);
 155.737 +}
 155.738 +
 155.739 +int svga_init()
 155.740 +{
 155.741 +        int c, d, e;
 155.742 +        for (c = 0; c < 256; c++)
 155.743 +        {
 155.744 +                e = c;
 155.745 +                for (d = 0; d < 8; d++)
 155.746 +                {
 155.747 +                        svga_rotate[d][c] = e;
 155.748 +                        e = (e >> 1) | ((e & 1) ? 0x80 : 0);
 155.749 +                }
 155.750 +        }
 155.751 +        readmode = 0;
 155.752 +        return 0;
 155.753 +}
 155.754 +
 155.755 +#define egacycles 1
 155.756 +#define egacycles2 1
 155.757 +void svga_write(uint32_t addr, uint8_t val)
 155.758 +{
 155.759 +        int x,y;
 155.760 +        char s[2]={0,0};
 155.761 +        uint8_t vala,valb,valc,vald,wm=writemask;
 155.762 +        int writemask2 = writemask;
 155.763 +        int bankaddr;
 155.764 +
 155.765 +        egawrites++;
 155.766 +
 155.767 +        cycles -= video_timing_b;
 155.768 +        cycles_lost += video_timing_b;
 155.769 +
 155.770 +//        pclog("Writeega %06X   ",addr);
 155.771 +        if (addr>=0xB0000) addr&=0x7FFF;
 155.772 +        else
 155.773 +        {
 155.774 +                //if (gdcreg[6]&8) return;
 155.775 +                addr &= 0xFFFF;
 155.776 +                addr += svgawbank;
 155.777 +        }
 155.778 +
 155.779 +        if (!(gdcreg[6]&1)) fullchange=2;
 155.780 +        if (chain4)
 155.781 +        {
 155.782 +                writemask2=1<<(addr&3);
 155.783 +                addr&=~3;
 155.784 +        }
 155.785 +        else
 155.786 +        {
 155.787 +                addr<<=2;
 155.788 +        }
 155.789 +//        pclog("%08X %02X %i %i %i\n", addr, val, writemask2, writemode, chain4);
 155.790 +        addr&=0x7FFFFF;
 155.791 +        changedvram[addr>>10]=changeframecount;
 155.792 +
 155.793 +        switch (writemode)
 155.794 +        {
 155.795 +                case 1:
 155.796 +                if (writemask2&1) vram[addr]=la;
 155.797 +                if (writemask2&2) vram[addr|0x1]=lb;
 155.798 +                if (writemask2&4) vram[addr|0x2]=lc;
 155.799 +                if (writemask2&8) vram[addr|0x3]=ld;
 155.800 +                break;
 155.801 +                case 0:
 155.802 +                if (gdcreg[3]&7) val=svga_rotate[gdcreg[3]&7][val];
 155.803 +                if (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1])
 155.804 +                {
 155.805 +                        if (writemask2&1) vram[addr]=val;
 155.806 +                        if (writemask2&2) vram[addr|0x1]=val;
 155.807 +                        if (writemask2&4) vram[addr|0x2]=val;
 155.808 +                        if (writemask2&8) vram[addr|0x3]=val;
 155.809 +                }
 155.810 +                else
 155.811 +                {
 155.812 +                        if (gdcreg[1]&1) vala=(gdcreg[0]&1)?0xFF:0;
 155.813 +                        else             vala=val;
 155.814 +                        if (gdcreg[1]&2) valb=(gdcreg[0]&2)?0xFF:0;
 155.815 +                        else             valb=val;
 155.816 +                        if (gdcreg[1]&4) valc=(gdcreg[0]&4)?0xFF:0;
 155.817 +                        else             valc=val;
 155.818 +                        if (gdcreg[1]&8) vald=(gdcreg[0]&8)?0xFF:0;
 155.819 +                        else             vald=val;
 155.820 +
 155.821 +                        switch (gdcreg[3]&0x18)
 155.822 +                        {
 155.823 +                                case 0: /*Set*/
 155.824 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
 155.825 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
 155.826 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
 155.827 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
 155.828 +                                break;
 155.829 +                                case 8: /*AND*/
 155.830 +                                if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
 155.831 +                                if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
 155.832 +                                if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
 155.833 +                                if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
 155.834 +                                break;
 155.835 +                                case 0x10: /*OR*/
 155.836 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
 155.837 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
 155.838 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
 155.839 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
 155.840 +                                break;
 155.841 +                                case 0x18: /*XOR*/
 155.842 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
 155.843 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
 155.844 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
 155.845 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
 155.846 +                                break;
 155.847 +                        }
 155.848 +//                        pclog("- %02X %02X %02X %02X   %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
 155.849 +                }
 155.850 +                break;
 155.851 +                case 2:
 155.852 +                if (!(gdcreg[3]&0x18) && !gdcreg[1])
 155.853 +                {
 155.854 +                        if (writemask2&1) vram[addr]=(((val&1)?0xFF:0)&gdcreg[8])|(la&~gdcreg[8]);
 155.855 +                        if (writemask2&2) vram[addr|0x1]=(((val&2)?0xFF:0)&gdcreg[8])|(lb&~gdcreg[8]);
 155.856 +                        if (writemask2&4) vram[addr|0x2]=(((val&4)?0xFF:0)&gdcreg[8])|(lc&~gdcreg[8]);
 155.857 +                        if (writemask2&8) vram[addr|0x3]=(((val&8)?0xFF:0)&gdcreg[8])|(ld&~gdcreg[8]);
 155.858 +                }
 155.859 +                else
 155.860 +                {
 155.861 +                        vala=((val&1)?0xFF:0);
 155.862 +                        valb=((val&2)?0xFF:0);
 155.863 +                        valc=((val&4)?0xFF:0);
 155.864 +                        vald=((val&8)?0xFF:0);
 155.865 +                        switch (gdcreg[3]&0x18)
 155.866 +                        {
 155.867 +                                case 0: /*Set*/
 155.868 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
 155.869 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
 155.870 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
 155.871 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
 155.872 +                                break;
 155.873 +                                case 8: /*AND*/
 155.874 +                                if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
 155.875 +                                if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
 155.876 +                                if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
 155.877 +                                if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
 155.878 +                                break;
 155.879 +                                case 0x10: /*OR*/
 155.880 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
 155.881 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
 155.882 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
 155.883 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
 155.884 +                                break;
 155.885 +                                case 0x18: /*XOR*/
 155.886 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
 155.887 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
 155.888 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
 155.889 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
 155.890 +                                break;
 155.891 +                        }
 155.892 +                }
 155.893 +                break;
 155.894 +                case 3:
 155.895 +                if (gdcreg[3]&7) val=svga_rotate[gdcreg[3]&7][val];
 155.896 +                wm=gdcreg[8];
 155.897 +                gdcreg[8]&=val;
 155.898 +
 155.899 +                vala=(gdcreg[0]&1)?0xFF:0;
 155.900 +                valb=(gdcreg[0]&2)?0xFF:0;
 155.901 +                valc=(gdcreg[0]&4)?0xFF:0;
 155.902 +                vald=(gdcreg[0]&8)?0xFF:0;
 155.903 +                switch (gdcreg[3]&0x18)
 155.904 +                {
 155.905 +                        case 0: /*Set*/
 155.906 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
 155.907 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
 155.908 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
 155.909 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
 155.910 +                        break;
 155.911 +                        case 8: /*AND*/
 155.912 +                        if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
 155.913 +                        if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
 155.914 +                        if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
 155.915 +                        if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
 155.916 +                        break;
 155.917 +                        case 0x10: /*OR*/
 155.918 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
 155.919 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
 155.920 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
 155.921 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
 155.922 +                        break;
 155.923 +                        case 0x18: /*XOR*/
 155.924 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
 155.925 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
 155.926 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
 155.927 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
 155.928 +                        break;
 155.929 +                }
 155.930 +                gdcreg[8]=wm;
 155.931 +                break;
 155.932 +        }
 155.933 +}
 155.934 +
 155.935 +uint8_t svga_read(uint32_t addr)
 155.936 +{
 155.937 +        uint8_t temp,temp2,temp3,temp4;
 155.938 +        uint32_t addr2;
 155.939 +        
 155.940 +        cycles -= video_timing_b;
 155.941 +        cycles_lost += video_timing_b;
 155.942 +        
 155.943 +        egareads++;
 155.944 +//        pclog("Readega %06X   ",addr);
 155.945 +        if (addr>=0xB0000) addr&=0x7FFF;
 155.946 +        else
 155.947 +        {
 155.948 +                addr &= 0xFFFF;
 155.949 +                addr += svgarbank;
 155.950 +        }
 155.951 +//        pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], readmode);
 155.952 +//        pclog("%i\n", readmode);
 155.953 +        if (chain4) 
 155.954 +        { 
 155.955 +                addr &= 0x7fffff;
 155.956 +                if (addr >= svga_vram_limit)
 155.957 +                   return 0xff;
 155.958 +                return vram[addr];
 155.959 +        }
 155.960 +        else        addr<<=2;
 155.961 +        
 155.962 +        addr &= 0x7fffff;
 155.963 +        
 155.964 +        if (addr >= svga_vram_limit)
 155.965 +           return 0xff;
 155.966 +           
 155.967 +        la=vram[addr];
 155.968 +        lb=vram[addr|0x1];
 155.969 +        lc=vram[addr|0x2];
 155.970 +        ld=vram[addr|0x3];
 155.971 +        if (readmode)
 155.972 +        {
 155.973 +                temp= (colournocare&1) ?0xFF:0;
 155.974 +                temp&=la;
 155.975 +                temp^=(colourcompare&1)?0xFF:0;
 155.976 +                temp2= (colournocare&2) ?0xFF:0;
 155.977 +                temp2&=lb;
 155.978 +                temp2^=(colourcompare&2)?0xFF:0;
 155.979 +                temp3= (colournocare&4) ?0xFF:0;
 155.980 +                temp3&=lc;
 155.981 +                temp3^=(colourcompare&4)?0xFF:0;
 155.982 +                temp4= (colournocare&8) ?0xFF:0;
 155.983 +                temp4&=ld;
 155.984 +                temp4^=(colourcompare&8)?0xFF:0;
 155.985 +                return ~(temp|temp2|temp3|temp4);
 155.986 +        }
 155.987 +//pclog("Read %02X %04X %04X\n",vram[addr|readplane],addr,readplane);
 155.988 +        return vram[addr|readplane];
 155.989 +}
 155.990 +
 155.991 +void svga_write_linear(uint32_t addr, uint8_t val)
 155.992 +{
 155.993 +        int x,y;
 155.994 +        char s[2]={0,0};
 155.995 +        uint8_t vala,valb,valc,vald,wm=writemask;
 155.996 +        int writemask2 = writemask;
 155.997 +        int bankaddr;
 155.998 +
 155.999 +        cycles -= video_timing_b;
155.1000 +        cycles_lost += video_timing_b;
155.1001 +
155.1002 +        egawrites++;
155.1003 +        
155.1004 +//        pclog("Write LFB %08X %02X ", addr, val);
155.1005 +        if (!(gdcreg[6]&1)) fullchange=2;
155.1006 +        if (chain4)
155.1007 +        {
155.1008 +                writemask2=1<<(addr&3);
155.1009 +                addr&=~3;
155.1010 +        }
155.1011 +        else
155.1012 +        {
155.1013 +                addr<<=2;
155.1014 +        }
155.1015 +        addr &= 0x7fffff;
155.1016 +//        pclog("%08X\n", addr);
155.1017 +        changedvram[addr>>10]=changeframecount;
155.1018 +        
155.1019 +        switch (writemode)
155.1020 +        {
155.1021 +                case 1:
155.1022 +                if (writemask2&1) vram[addr]=la;
155.1023 +                if (writemask2&2) vram[addr|0x1]=lb;
155.1024 +                if (writemask2&4) vram[addr|0x2]=lc;
155.1025 +                if (writemask2&8) vram[addr|0x3]=ld;
155.1026 +                break;
155.1027 +                case 0:
155.1028 +                if (gdcreg[3]&7) val=svga_rotate[gdcreg[3]&7][val];
155.1029 +                if (gdcreg[8]==0xFF && !(gdcreg[3]&0x18) && !gdcreg[1])
155.1030 +                {
155.1031 +                        if (writemask2&1) vram[addr]=val;
155.1032 +                        if (writemask2&2) vram[addr|0x1]=val;
155.1033 +                        if (writemask2&4) vram[addr|0x2]=val;
155.1034 +                        if (writemask2&8) vram[addr|0x3]=val;
155.1035 +                }
155.1036 +                else
155.1037 +                {
155.1038 +                        if (gdcreg[1]&1) vala=(gdcreg[0]&1)?0xFF:0;
155.1039 +                        else             vala=val;
155.1040 +                        if (gdcreg[1]&2) valb=(gdcreg[0]&2)?0xFF:0;
155.1041 +                        else             valb=val;
155.1042 +                        if (gdcreg[1]&4) valc=(gdcreg[0]&4)?0xFF:0;
155.1043 +                        else             valc=val;
155.1044 +                        if (gdcreg[1]&8) vald=(gdcreg[0]&8)?0xFF:0;
155.1045 +                        else             vald=val;
155.1046 +
155.1047 +                        switch (gdcreg[3]&0x18)
155.1048 +                        {
155.1049 +                                case 0: /*Set*/
155.1050 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
155.1051 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
155.1052 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
155.1053 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
155.1054 +                                break;
155.1055 +                                case 8: /*AND*/
155.1056 +                                if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
155.1057 +                                if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
155.1058 +                                if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
155.1059 +                                if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
155.1060 +                                break;
155.1061 +                                case 0x10: /*OR*/
155.1062 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
155.1063 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
155.1064 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
155.1065 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
155.1066 +                                break;
155.1067 +                                case 0x18: /*XOR*/
155.1068 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
155.1069 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
155.1070 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
155.1071 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
155.1072 +                                break;
155.1073 +                        }
155.1074 +//                        pclog("- %02X %02X %02X %02X   %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
155.1075 +                }
155.1076 +                break;
155.1077 +                case 2:
155.1078 +                if (!(gdcreg[3]&0x18) && !gdcreg[1])
155.1079 +                {
155.1080 +                        if (writemask2&1) vram[addr]=(((val&1)?0xFF:0)&gdcreg[8])|(la&~gdcreg[8]);
155.1081 +                        if (writemask2&2) vram[addr|0x1]=(((val&2)?0xFF:0)&gdcreg[8])|(lb&~gdcreg[8]);
155.1082 +                        if (writemask2&4) vram[addr|0x2]=(((val&4)?0xFF:0)&gdcreg[8])|(lc&~gdcreg[8]);
155.1083 +                        if (writemask2&8) vram[addr|0x3]=(((val&8)?0xFF:0)&gdcreg[8])|(ld&~gdcreg[8]);
155.1084 +                }
155.1085 +                else
155.1086 +                {
155.1087 +                        vala=((val&1)?0xFF:0);
155.1088 +                        valb=((val&2)?0xFF:0);
155.1089 +                        valc=((val&4)?0xFF:0);
155.1090 +                        vald=((val&8)?0xFF:0);
155.1091 +                        switch (gdcreg[3]&0x18)
155.1092 +                        {
155.1093 +                                case 0: /*Set*/
155.1094 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
155.1095 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
155.1096 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
155.1097 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
155.1098 +                                break;
155.1099 +                                case 8: /*AND*/
155.1100 +                                if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
155.1101 +                                if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
155.1102 +                                if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
155.1103 +                                if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
155.1104 +                                break;
155.1105 +                                case 0x10: /*OR*/
155.1106 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
155.1107 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
155.1108 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
155.1109 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
155.1110 +                                break;
155.1111 +                                case 0x18: /*XOR*/
155.1112 +                                if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
155.1113 +                                if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
155.1114 +                                if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
155.1115 +                                if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
155.1116 +                                break;
155.1117 +                        }
155.1118 +                }
155.1119 +                break;
155.1120 +                case 3:
155.1121 +                if (gdcreg[3]&7) val=svga_rotate[gdcreg[3]&7][val];
155.1122 +                wm=gdcreg[8];
155.1123 +                gdcreg[8]&=val;
155.1124 +
155.1125 +                vala=(gdcreg[0]&1)?0xFF:0;
155.1126 +                valb=(gdcreg[0]&2)?0xFF:0;
155.1127 +                valc=(gdcreg[0]&4)?0xFF:0;
155.1128 +                vald=(gdcreg[0]&8)?0xFF:0;
155.1129 +                switch (gdcreg[3]&0x18)
155.1130 +                {
155.1131 +                        case 0: /*Set*/
155.1132 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])|(la&~gdcreg[8]);
155.1133 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|(lb&~gdcreg[8]);
155.1134 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|(lc&~gdcreg[8]);
155.1135 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|(ld&~gdcreg[8]);
155.1136 +                        break;
155.1137 +                        case 8: /*AND*/
155.1138 +                        if (writemask2&1) vram[addr]=(vala|~gdcreg[8])&la;
155.1139 +                        if (writemask2&2) vram[addr|0x1]=(valb|~gdcreg[8])&lb;
155.1140 +                        if (writemask2&4) vram[addr|0x2]=(valc|~gdcreg[8])&lc;
155.1141 +                        if (writemask2&8) vram[addr|0x3]=(vald|~gdcreg[8])&ld;
155.1142 +                        break;
155.1143 +                        case 0x10: /*OR*/
155.1144 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])|la;
155.1145 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])|lb;
155.1146 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])|lc;
155.1147 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])|ld;
155.1148 +                        break;
155.1149 +                        case 0x18: /*XOR*/
155.1150 +                        if (writemask2&1) vram[addr]=(vala&gdcreg[8])^la;
155.1151 +                        if (writemask2&2) vram[addr|0x1]=(valb&gdcreg[8])^lb;
155.1152 +                        if (writemask2&4) vram[addr|0x2]=(valc&gdcreg[8])^lc;
155.1153 +                        if (writemask2&8) vram[addr|0x3]=(vald&gdcreg[8])^ld;
155.1154 +                        break;
155.1155 +                }
155.1156 +                gdcreg[8]=wm;
155.1157 +                break;
155.1158 +        }
155.1159 +}
155.1160 +
155.1161 +uint8_t svga_read_linear(uint32_t addr)
155.1162 +{
155.1163 +        uint8_t temp,temp2,temp3,temp4;
155.1164 +  
155.1165 +        cycles -= video_timing_b;
155.1166 +        cycles_lost += video_timing_b;
155.1167 +
155.1168 +        egareads++;
155.1169 +        
155.1170 +        if (chain4) 
155.1171 +        { 
155.1172 +                addr &= 0x7fffff;
155.1173 +                if (addr >= svga_vram_limit)
155.1174 +                   return 0xff;
155.1175 +                return vram[addr & 0x7fffff]; 
155.1176 +        }
155.1177 +        else        addr<<=2;
155.1178 +
155.1179 +        addr &= 0x7fffff;
155.1180 +        
155.1181 +        if (addr >= svga_vram_limit)
155.1182 +           return 0xff;
155.1183 +
155.1184 +        la=vram[addr];
155.1185 +        lb=vram[addr|0x1];
155.1186 +        lc=vram[addr|0x2];
155.1187 +        ld=vram[addr|0x3];
155.1188 +        if (readmode)
155.1189 +        {
155.1190 +                temp= (colournocare&1) ?0xFF:0;
155.1191 +                temp&=la;
155.1192 +                temp^=(colourcompare&1)?0xFF:0;
155.1193 +                temp2= (colournocare&2) ?0xFF:0;
155.1194 +                temp2&=lb;
155.1195 +                temp2^=(colourcompare&2)?0xFF:0;
155.1196 +                temp3= (colournocare&4) ?0xFF:0;
155.1197 +                temp3&=lc;
155.1198 +                temp3^=(colourcompare&4)?0xFF:0;
155.1199 +                temp4= (colournocare&8) ?0xFF:0;
155.1200 +                temp4&=ld;
155.1201 +                temp4^=(colourcompare&8)?0xFF:0;
155.1202 +                return ~(temp|temp2|temp3|temp4);
155.1203 +        }
155.1204 +//printf("Read %02X %04X %04X\n",vram[addr|readplane],addr,readplane);
155.1205 +        return vram[addr|readplane];
155.1206 +}
155.1207 +
155.1208 +void svga_doblit(int y1, int y2)
155.1209 +{
155.1210 +        frames++;
155.1211 +//        pclog("doblit %i %i\n", y1, y2);
155.1212 +        if (y1 > y2) 
155.1213 +        {
155.1214 +                startblit();
155.1215 +                video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize);
155.1216 +                endblit();
155.1217 +                return;   
155.1218 +        }     
155.1219 +        startblit();
155.1220 +        if ((wx!=xsize || wy!=ysize) && !vid_resize)
155.1221 +        {
155.1222 +                xsize=wx;
155.1223 +                ysize=wy+1;
155.1224 +                if (xsize<64) xsize=656;
155.1225 +                if (ysize<32) ysize=200;
155.1226 +                if (vres) updatewindowsize(xsize,ysize<<1);
155.1227 +                else      updatewindowsize(xsize,ysize);
155.1228 +        }
155.1229 +        if (vid_resize)
155.1230 +        {
155.1231 +                xsize = wx;
155.1232 +                ysize = wy + 1;
155.1233 +        }
155.1234 +        video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
155.1235 +        if (readflash) rectfill(screen,winsizex-40,8,winsizex-8,14,0xFFFFFFFF);
155.1236 +        endblit();
155.1237 +        
155.1238 +}
155.1239 +
155.1240 +void svga_writew(uint32_t addr, uint16_t val)
155.1241 +{
155.1242 +        if (!svga_fast)
155.1243 +        {
155.1244 +                svga_write(addr, val);
155.1245 +                svga_write(addr + 1, val >> 8);
155.1246 +                return;
155.1247 +        }
155.1248 +        
155.1249 +        egawrites += 2;
155.1250 +
155.1251 +        cycles -= video_timing_w;
155.1252 +        cycles_lost += video_timing_w;
155.1253 +
155.1254 +//        pclog("Writew %05X ", addr);
155.1255 +        addr = (addr & 0xffff) + svgawbank;
155.1256 +        addr &= 0x7FFFFF;        
155.1257 +//        pclog("%08X %04X\n", addr, val);
155.1258 +        changedvram[addr >> 10] = changeframecount;
155.1259 +        *(uint16_t *)&vram[addr] = val;
155.1260 +}
155.1261 +
155.1262 +void svga_writel(uint32_t addr, uint32_t val)
155.1263 +{
155.1264 +        if (!svga_fast)
155.1265 +        {
155.1266 +                svga_write(addr, val);
155.1267 +                svga_write(addr + 1, val >> 8);
155.1268 +                svga_write(addr + 2, val >> 16);
155.1269 +                svga_write(addr + 3, val >> 24);
155.1270 +                return;
155.1271 +        }
155.1272 +        
155.1273 +        egawrites += 4;
155.1274 +
155.1275 +        cycles -= video_timing_l;
155.1276 +        cycles_lost += video_timing_l;
155.1277 +
155.1278 +//        pclog("Writel %05X ", addr);
155.1279 +        addr = (addr & 0xffff) + svgawbank;
155.1280 +        addr &= 0x7FFFFF;
155.1281 +//        pclog("%08X %08X\n", addr, val);
155.1282 +        
155.1283 +        changedvram[addr >> 10] = changeframecount;
155.1284 +        *(uint32_t *)&vram[addr] = val;
155.1285 +}
155.1286 +
155.1287 +uint16_t svga_readw(uint32_t addr)
155.1288 +{
155.1289 +        if (!svga_fast)
155.1290 +           return svga_read(addr) | (svga_read(addr + 1) << 8);
155.1291 +        
155.1292 +        egareads += 2;
155.1293 +
155.1294 +        cycles -= video_timing_w;
155.1295 +        cycles_lost += video_timing_w;
155.1296 +
155.1297 +//        pclog("Readw %05X ", addr);
155.1298 +        addr = (addr & 0xffff) + svgarbank;
155.1299 +        addr &= 0x7FFFFF;
155.1300 +//        pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]);
155.1301 +        if (addr >= svga_vram_limit) return 0xffff;
155.1302 +        
155.1303 +        return *(uint16_t *)&vram[addr];
155.1304 +}
155.1305 +
155.1306 +uint32_t svga_readl(uint32_t addr)
155.1307 +{
155.1308 +        if (!svga_fast)
155.1309 +           return svga_read(addr) | (svga_read(addr + 1) << 8) | (svga_read(addr + 2) << 16) | (svga_read(addr + 3) << 24);
155.1310 +        
155.1311 +        egareads += 4;
155.1312 +
155.1313 +        cycles -= video_timing_l;
155.1314 +        cycles_lost += video_timing_l;
155.1315 +
155.1316 +//        pclog("Readl %05X ", addr);
155.1317 +        addr = (addr & 0xffff) + svgarbank;
155.1318 +        addr &= 0x7FFFFF;
155.1319 +//        pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]);
155.1320 +        if (addr >= svga_vram_limit) return 0xffffffff;
155.1321 +        
155.1322 +        return *(uint32_t *)&vram[addr];
155.1323 +}
155.1324 +
155.1325 +void svga_writew_linear(uint32_t addr, uint16_t val)
155.1326 +{
155.1327 +        if (!svga_fast)
155.1328 +        {
155.1329 +                svga_write_linear(addr, val);
155.1330 +                svga_write_linear(addr + 1, val >> 8);
155.1331 +                return;
155.1332 +        }
155.1333 +        
155.1334 +        egawrites += 2;
155.1335 +
155.1336 +        cycles -= video_timing_w;
155.1337 +        cycles_lost += video_timing_w;
155.1338 +
155.1339 +        addr &= 0x7FFFFF;
155.1340 +        changedvram[addr >> 10] = changeframecount;
155.1341 +        *(uint16_t *)&vram[addr] = val;
155.1342 +}
155.1343 +
155.1344 +void svga_writel_linear(uint32_t addr, uint32_t val)
155.1345 +{
155.1346 +        if (!svga_fast)
155.1347 +        {
155.1348 +                svga_write_linear(addr, val);
155.1349 +                svga_write_linear(addr + 1, val >> 8);
155.1350 +                svga_write_linear(addr + 2, val >> 16);
155.1351 +                svga_write_linear(addr + 3, val >> 24);
155.1352 +                return;
155.1353 +        }
155.1354 +        
155.1355 +        egawrites += 4;
155.1356 +
155.1357 +        cycles -= video_timing_l;
155.1358 +        cycles_lost += video_timing_l;
155.1359 +
155.1360 +        addr &= 0x7fffff;
155.1361 +        changedvram[addr >> 10] = changeframecount;
155.1362 +        *(uint32_t *)&vram[addr] = val;
155.1363 +}
155.1364 +
155.1365 +uint16_t svga_readw_linear(uint32_t addr)
155.1366 +{
155.1367 +        if (!svga_fast)
155.1368 +           return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8);
155.1369 +        
155.1370 +        egareads += 2;
155.1371 +
155.1372 +        cycles -= video_timing_w;
155.1373 +        cycles_lost += video_timing_w;
155.1374 +
155.1375 +        addr &= 0x7FFFFF;
155.1376 +        if (addr >= svga_vram_limit) return 0xffff;
155.1377 +        
155.1378 +        return *(uint16_t *)&vram[addr];
155.1379 +}
155.1380 +
155.1381 +uint32_t svga_readl_linear(uint32_t addr)
155.1382 +{
155.1383 +        if (!svga_fast)
155.1384 +           return svga_read_linear(addr) | (svga_read_linear(addr + 1) << 8) | (svga_read_linear(addr + 2) << 16) | (svga_read_linear(addr + 3) << 24);
155.1385 +        
155.1386 +        egareads += 4;
155.1387 +
155.1388 +        cycles -= video_timing_l;
155.1389 +        cycles_lost += video_timing_l;
155.1390 +
155.1391 +        addr &= 0x7FFFFF;
155.1392 +        if (addr >= svga_vram_limit) return 0xffffffff;
155.1393 +
155.1394 +        return *(uint32_t *)&vram[addr];
155.1395 +}
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/src/vid_svga.h	Sun Apr 21 14:54:35 2013 +0100
   156.3 @@ -0,0 +1,53 @@
   156.4 +/*Vertical timings*/
   156.5 +extern int svga_vtotal, svga_dispend, svga_vsyncstart, svga_split;
   156.6 +/*Horizontal timings*/
   156.7 +extern int svga_hdisp, svga_htotal, svga_rowoffset;
   156.8 +/*Flags - svga_lowres = 1/2 clock in 256+ colour modes, svga_interlace = interlace mode enabled*/
   156.9 +extern int svga_lowres, svga_interlace;
  156.10 +
  156.11 +/*Status of display on*/
  156.12 +extern int svga_hdisp_on;
  156.13 +
  156.14 +extern double svga_clock;
  156.15 +extern uint32_t svga_ma;
  156.16 +extern void (*svga_recalctimings_ex)();
  156.17 +
  156.18 +extern uint8_t svga_miscout;
  156.19 +
  156.20 +extern int  svga_init();
  156.21 +extern void svga_poll();
  156.22 +extern void svga_recalctimings();
  156.23 +
  156.24 +typedef struct
  156.25 +{
  156.26 +        int ena;
  156.27 +        int x, y;
  156.28 +        int xoff, yoff;
  156.29 +        uint32_t addr;
  156.30 +} SVGA_HWCURSOR;
  156.31 +
  156.32 +extern SVGA_HWCURSOR svga_hwcursor, svga_hwcursor_latch;
  156.33 +
  156.34 +//extern int      svga_hwcursor_x,    svga_hwcursor_y;
  156.35 +//extern int      svga_hwcursor_xoff, svga_hwcursor_yoff;
  156.36 +//extern uint32_t /*svga_hwcursor_addr, */svga_hwcursor_addr_cur;
  156.37 +//extern int      svga_hwcursor_ena;
  156.38 +extern int      svga_hwcursor_on;
  156.39 +extern void   (*svga_hwcursor_draw)(int displine);
  156.40 +
  156.41 +uint8_t  svga_read(uint32_t addr);
  156.42 +uint16_t svga_readw(uint32_t addr);
  156.43 +uint32_t svga_readl(uint32_t addr);
  156.44 +void     svga_write(uint32_t addr, uint8_t val);
  156.45 +void     svga_writew(uint32_t addr, uint16_t val);
  156.46 +void     svga_writel(uint32_t addr, uint32_t val);
  156.47 +uint8_t  svga_read_linear(uint32_t addr);
  156.48 +uint16_t svga_readw_linear(uint32_t addr);
  156.49 +uint32_t svga_readl_linear(uint32_t addr);
  156.50 +void     svga_write_linear(uint32_t addr, uint8_t val);
  156.51 +void     svga_writew_linear(uint32_t addr, uint16_t val);
  156.52 +void     svga_writel_linear(uint32_t addr, uint32_t val);
  156.53 +
  156.54 +void svga_doblit(int y1, int y2);
  156.55 +
  156.56 +extern uint32_t svga_vram_limit;
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/src/vid_tandy.c	Sun Apr 21 14:54:35 2013 +0100
   157.3 @@ -0,0 +1,611 @@
   157.4 +#include "ibm.h"
   157.5 +#include "video.h"
   157.6 +#include "io.h"
   157.7 +#include "mem.h"
   157.8 +
   157.9 +static int      tandy_array_index;
  157.10 +static uint8_t  tandy_array[32];
  157.11 +static int      tandy_memctrl=-1;
  157.12 +static uint32_t tandy_base;
  157.13 +static uint8_t  tandy_mode,tandy_col;
  157.14 +
  157.15 +static uint8_t *tandy_vram, *tandy_b8000;
  157.16 +
  157.17 +void tandy_recalcaddress();
  157.18 +void tandy_recalctimings();
  157.19 +        
  157.20 +void tandy_out(uint16_t addr, uint8_t val)
  157.21 +{
  157.22 +        uint8_t old;
  157.23 +//        pclog("Tandy OUT %04X %02X\n",addr,val);
  157.24 +        switch (addr)
  157.25 +        {
  157.26 +                case 0x3D4:
  157.27 +                crtcreg=val&31;
  157.28 +                return;
  157.29 +                case 0x3D5:
  157.30 +                old=crtc[crtcreg];
  157.31 +                crtc[crtcreg]=val&crtcmask[crtcreg];
  157.32 +                if (old!=val)
  157.33 +                {
  157.34 +                        if (crtcreg<0xE || crtcreg>0x10)
  157.35 +                        {
  157.36 +                                fullchange=changeframecount;
  157.37 +                                tandy_recalctimings();
  157.38 +                        }
  157.39 +                }
  157.40 +                return;
  157.41 +                case 0x3D8:
  157.42 +                tandy_mode=val;
  157.43 +                return;
  157.44 +                case 0x3D9:
  157.45 +                tandy_col=val;
  157.46 +                return;
  157.47 +                case 0x3DA:
  157.48 +                tandy_array_index = val & 31;
  157.49 +                break;
  157.50 +                case 0x3DE:
  157.51 +                if (tandy_array_index & 16) val &= 0xF;
  157.52 +                tandy_array[tandy_array_index & 31] = val;
  157.53 +                break;
  157.54 +                case 0x3DF:
  157.55 +                tandy_memctrl=val;
  157.56 +                tandy_recalcaddress();
  157.57 +                break;
  157.58 +                case 0xA0:
  157.59 +                tandy_base=((val>>1)&7)*128*1024;
  157.60 +                tandy_recalcaddress();
  157.61 +                break;
  157.62 +        }
  157.63 +}
  157.64 +
  157.65 +uint8_t tandy_in(uint16_t addr)
  157.66 +{
  157.67 +//        if (addr!=0x3DA) pclog("Tandy IN %04X\n",addr);
  157.68 +        switch (addr)
  157.69 +        {
  157.70 +                case 0x3D4:
  157.71 +                return crtcreg;
  157.72 +                case 0x3D5:
  157.73 +                return crtc[crtcreg];
  157.74 +                case 0x3DA:
  157.75 +                return cgastat;
  157.76 +        }
  157.77 +        return 0xFF;
  157.78 +}
  157.79 +
  157.80 +void tandy_recalcaddress()
  157.81 +{
  157.82 +        if ((tandy_memctrl&0xC0)==0xC0)
  157.83 +        {
  157.84 +                tandy_vram =&ram[((tandy_memctrl&0x6)<<14) +tandy_base];
  157.85 +                tandy_b8000=&ram[((tandy_memctrl&0x30)<<11)+tandy_base];
  157.86 +//                printf("VRAM at %05X B8000 at %05X\n",((tandy_memctrl&0x6)<<14)+tandy_base,((tandy_memctrl&0x30)<<11)+tandy_base);
  157.87 +        }
  157.88 +        else
  157.89 +        {
  157.90 +                tandy_vram =&ram[((tandy_memctrl&0x7)<<14) +tandy_base];
  157.91 +                tandy_b8000=&ram[((tandy_memctrl&0x38)<<11)+tandy_base];
  157.92 +//                printf("VRAM at %05X B8000 at %05X\n",((tandy_memctrl&0x7)<<14)+tandy_base,((tandy_memctrl&0x38)<<11)+tandy_base);
  157.93 +        }
  157.94 +}
  157.95 +
  157.96 +void tandy_write(uint32_t addr, uint8_t val)
  157.97 +{
  157.98 +        if (tandy_memctrl==-1) return;
  157.99 +//        pclog("Tandy VRAM write %05X %02X %04X:%04X  %04X:%04X\n",addr,val,CS,pc,DS,SI);
 157.100 +        tandy_b8000[addr&0x7FFF]=val;
 157.101 +}
 157.102 +
 157.103 +uint8_t tandy_read(uint32_t addr)
 157.104 +{
 157.105 +        if (tandy_memctrl==-1) return 0xFF;
 157.106 +//        pclog("Tandy VRAM read  %05X %02X %04X:%04X\n",addr,tandy_b8000[addr&0x7FFF],CS,pc);
 157.107 +        return tandy_b8000[addr&0x7FFF];
 157.108 +}
 157.109 +
 157.110 +void tandy_recalctimings()
 157.111 +{
 157.112 +        if (tandy_mode&1)
 157.113 +        {
 157.114 +                disptime=crtc[0]+1;
 157.115 +                dispontime=crtc[1];
 157.116 +        }
 157.117 +        else
 157.118 +        {
 157.119 +                disptime=(crtc[0]+1)<<1;
 157.120 +                dispontime=crtc[1]<<1;
 157.121 +        }
 157.122 +        dispofftime=disptime-dispontime;
 157.123 +        dispontime*=CGACONST;
 157.124 +        dispofftime*=CGACONST;
 157.125 +}
 157.126 +
 157.127 +
 157.128 +static int linepos,displine;
 157.129 +static int sc,vc;
 157.130 +static int cgadispon;
 157.131 +static int con,coff,cursoron,cgablink;
 157.132 +static int vsynctime,vadj;
 157.133 +static uint16_t ma,maback,ca;
 157.134 +
 157.135 +static int ntsc_col[8][8]=
 157.136 +{
 157.137 +        {0,0,0,0,0,0,0,0}, /*Black*/
 157.138 +        {0,0,1,1,1,1,0,0}, /*Blue*/
 157.139 +        {1,0,0,0,0,1,1,1}, /*Green*/
 157.140 +        {0,0,0,0,1,1,1,1}, /*Cyan*/
 157.141 +        {1,1,1,1,0,0,0,0}, /*Red*/
 157.142 +        {0,1,1,1,1,0,0,0}, /*Magenta*/
 157.143 +        {1,1,0,0,0,0,1,1}, /*Yellow*/
 157.144 +        {1,1,1,1,1,1,1,1}  /*White*/
 157.145 +};
 157.146 +
 157.147 +int i_filt[8],q_filt[8];
 157.148 +
 157.149 +/*static int cga4pal[8][4]=
 157.150 +{
 157.151 +        {0,2,4,6},{0,3,5,7},{0,3,4,7},{0,3,4,7},
 157.152 +        {0,10,12,14},{0,11,13,15},{0,11,12,15},{0,11,12,15}
 157.153 +};*/
 157.154 +
 157.155 +void tandy_poll()
 157.156 +{
 157.157 +//        int *cgapal=cga4pal[((tandy_col&0x10)>>2)|((cgamode&4)>>1)|((cgacol&0x20)>>5)];
 157.158 +        uint16_t ca=(crtc[15]|(crtc[14]<<8))&0x3FFF;
 157.159 +        int drawcursor;
 157.160 +        int x,c;
 157.161 +        int oldvc;
 157.162 +        uint8_t chr,attr;
 157.163 +        uint16_t dat,dat2,dat3,dat4;
 157.164 +        int cols[4];
 157.165 +        int col;
 157.166 +        int oldsc;
 157.167 +        int y_buf[8]={0,0,0,0,0,0,0,0},y_val,y_tot;
 157.168 +        int i_buf[8]={0,0,0,0,0,0,0,0},i_val,i_tot;
 157.169 +        int q_buf[8]={0,0,0,0,0,0,0,0},q_val,q_tot;
 157.170 +        int r,g,b;
 157.171 +        if (!linepos)
 157.172 +        {
 157.173 +//                cgapal[0]=tandy_col&15;
 157.174 +//                printf("Firstline %i Lastline %i Displine %i\n",firstline,lastline,displine);
 157.175 +                vidtime+=dispofftime;
 157.176 +                cgastat|=1;
 157.177 +                linepos=1;
 157.178 +                oldsc=sc;
 157.179 +                if ((crtc[8]&3)==3) sc=(sc<<1)&7;
 157.180 +                if (cgadispon)
 157.181 +                {
 157.182 +                        if (displine<firstline)
 157.183 +                        {
 157.184 +                                firstline=displine;
 157.185 +//                                printf("Firstline %i\n",firstline);
 157.186 +                        }
 157.187 +                        lastline=displine;
 157.188 +                        cols[0]=(tandy_array[2]&0xF)+16;
 157.189 +                        for (c=0;c<8;c++)
 157.190 +                        {
 157.191 +                                if (tandy_array[3]&4)
 157.192 +                                {
 157.193 +                                        buffer->line[displine][c]=cols[0];
 157.194 +                                        if (tandy_mode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=cols[0];
 157.195 +                                        else              buffer->line[displine][c+(crtc[1]<<4)+8]=cols[0];
 157.196 +                                }
 157.197 +                                else if ((tandy_mode&0x12)==0x12)
 157.198 +                                {
 157.199 +                                        buffer->line[displine][c]=0;
 157.200 +                                        if (tandy_mode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=0;
 157.201 +                                        else              buffer->line[displine][c+(crtc[1]<<4)+8]=0;
 157.202 +                                }
 157.203 +                                else
 157.204 +                                {
 157.205 +                                        buffer->line[displine][c]=(tandy_col&15)+16;
 157.206 +                                        if (tandy_mode&1) buffer->line[displine][c+(crtc[1]<<3)+8]=(tandy_col&15)+16;
 157.207 +                                        else              buffer->line[displine][c+(crtc[1]<<4)+8]=(tandy_col&15)+16;
 157.208 +                                }
 157.209 +                        }
 157.210 +//                        printf("X %i %i\n",c+(crtc[1]<<4)+8,c+(crtc[1]<<3)+8);
 157.211 +//                        printf("Drawing %i %i %i\n",displine,vc,sc);
 157.212 +                        if ((tandy_array[3]&0x10) && (tandy_mode&1)) /*320x200x16*/
 157.213 +                        {
 157.214 +                                for (x=0;x<crtc[1];x++)
 157.215 +                                {
 157.216 +                                        dat=(tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)]<<8)|tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)+1];
 157.217 +                                        ma++;
 157.218 +                                        buffer->line[displine][(x<<3)+8]=buffer->line[displine][(x<<3)+9]  =tandy_array[((dat>>12)&tandy_array[1])+16]+16;
 157.219 +                                        buffer->line[displine][(x<<3)+10]=buffer->line[displine][(x<<3)+11]=tandy_array[((dat>>8)&tandy_array[1])+16]+16;
 157.220 +                                        buffer->line[displine][(x<<3)+12]=buffer->line[displine][(x<<3)+13]=tandy_array[((dat>>4)&tandy_array[1])+16]+16;
 157.221 +                                        buffer->line[displine][(x<<3)+14]=buffer->line[displine][(x<<3)+15]=tandy_array[(dat&tandy_array[1])+16]+16;
 157.222 +                                }
 157.223 +                        }
 157.224 +                        else if (tandy_array[3]&0x10) /*160x200x16*/
 157.225 +                        {
 157.226 +                                for (x=0;x<crtc[1];x++)
 157.227 +                                {
 157.228 +                                        dat=(tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)]<<8)|tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)+1];
 157.229 +                                        ma++;
 157.230 +                                        buffer->line[displine][(x<<4)+8]= buffer->line[displine][(x<<4)+9]= buffer->line[displine][(x<<4)+10]=buffer->line[displine][(x<<4)+11]=tandy_array[((dat>>12)&tandy_array[1])+16]+16;
 157.231 +                                        buffer->line[displine][(x<<4)+12]=buffer->line[displine][(x<<4)+13]=buffer->line[displine][(x<<4)+14]=buffer->line[displine][(x<<4)+15]=tandy_array[((dat>>8)&tandy_array[1])+16]+16;
 157.232 +                                        buffer->line[displine][(x<<4)+16]=buffer->line[displine][(x<<4)+17]=buffer->line[displine][(x<<4)+18]=buffer->line[displine][(x<<4)+19]=tandy_array[((dat>>4)&tandy_array[1])+16]+16;
 157.233 +                                        buffer->line[displine][(x<<4)+20]=buffer->line[displine][(x<<4)+21]=buffer->line[displine][(x<<4)+22]=buffer->line[displine][(x<<4)+23]=tandy_array[(dat&tandy_array[1])+16]+16;
 157.234 +                                }
 157.235 +                        }
 157.236 +                        else if (tandy_array[3]&0x08) /*640x200x4 - this implementation is a complete guess!*/
 157.237 +                        {
 157.238 +                                for (x=0;x<crtc[1];x++)
 157.239 +                                {
 157.240 +                                        dat=(tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)]<<8)|tandy_vram[((ma<<1)&0x1FFF)+((sc&3)*0x2000)+1];
 157.241 +                                        ma++;
 157.242 +                                        for (c=0;c<8;c++)
 157.243 +                                        {
 157.244 +                                                chr=(dat>>7)&1;
 157.245 +                                                chr|=((dat>>14)&2);
 157.246 +                                                buffer->line[displine][(x<<3)+8+c]=tandy_array[(chr&tandy_array[1])+16]+16;
 157.247 +                                                dat<<=1;
 157.248 +                                        }
 157.249 +                                }
 157.250 +                        }
 157.251 +                        else if (tandy_mode&1)
 157.252 +                        {
 157.253 +                                for (x=0;x<crtc[1];x++)
 157.254 +                                {
 157.255 +                                        chr=tandy_vram[(ma<<1)&0x3FFF];
 157.256 +                                        attr=tandy_vram[((ma<<1)+1)&0x3FFF];
 157.257 +                                        drawcursor=((ma==ca) && con && cursoron);
 157.258 +                                        if (tandy_mode&0x20)
 157.259 +                                        {
 157.260 +                                                cols[1]=tandy_array[((attr&15)&tandy_array[1])+16]+16;
 157.261 +                                                cols[0]=tandy_array[(((attr>>4)&7)&tandy_array[1])+16]+16;
 157.262 +                                                if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
 157.263 +                                        }
 157.264 +                                        else
 157.265 +                                        {
 157.266 +                                                cols[1]=tandy_array[((attr&15)&tandy_array[1])+16]+16;
 157.267 +                                                cols[0]=tandy_array[((attr>>4)&tandy_array[1])+16]+16;
 157.268 +                                        }
 157.269 +                                        if (sc&8)
 157.270 +                                        {
 157.271 +                                                for (c=0;c<8;c++)
 157.272 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[0];
 157.273 +                                        }
 157.274 +                                        else
 157.275 +                                        {
 157.276 +                                                for (c=0;c<8;c++)
 157.277 +                                                    buffer->line[displine][(x<<3)+c+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 157.278 +                                        }
 157.279 +//                                        if (!((ma^(crtc[15]|(crtc[14]<<8)))&0x3FFF)) printf("Cursor match! %04X\n",ma);
 157.280 +                                        if (drawcursor)
 157.281 +                                        {
 157.282 +                                                for (c=0;c<8;c++)
 157.283 +                                                    buffer->line[displine][(x<<3)+c+8]^=15;
 157.284 +                                        }
 157.285 +                                        ma++;
 157.286 +                                }
 157.287 +                        }
 157.288 +                        else if (!(tandy_mode&2))
 157.289 +                        {
 157.290 +                                for (x=0;x<crtc[1];x++)
 157.291 +                                {
 157.292 +                                        chr=tandy_vram[(ma<<1)&0x3FFF];
 157.293 +                                        attr=tandy_vram[((ma<<1)+1)&0x3FFF];
 157.294 +                                        drawcursor=((ma==ca) && con && cursoron);
 157.295 +                                        if (tandy_mode&0x20)
 157.296 +                                        {
 157.297 +                                                cols[1]=tandy_array[((attr&15)&tandy_array[1])+16]+16;
 157.298 +                                                cols[0]=tandy_array[(((attr>>4)&7)&tandy_array[1])+16]+16;
 157.299 +                                                if ((cgablink&16) && (attr&0x80) && !drawcursor) cols[1]=cols[0];
 157.300 +                                        }
 157.301 +                                        else
 157.302 +                                        {
 157.303 +                                                cols[1]=tandy_array[((attr&15)&tandy_array[1])+16]+16;
 157.304 +                                                cols[0]=tandy_array[((attr>>4)&tandy_array[1])+16]+16;
 157.305 +                                        }
 157.306 +                                        ma++;
 157.307 +                                        if (sc&8)
 157.308 +                                        {
 157.309 +                                                for (c=0;c<8;c++)
 157.310 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[0];
 157.311 +                                        }
 157.312 +                                        else
 157.313 +                                        {
 157.314 +                                                for (c=0;c<8;c++)
 157.315 +                                                    buffer->line[displine][(x<<4)+(c<<1)+8]=buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[(fontdat[chr][sc&7]&(1<<(c^7)))?1:0];
 157.316 +                                        }
 157.317 +                                        if (drawcursor)
 157.318 +                                        {
 157.319 +                                                for (c=0;c<16;c++)
 157.320 +                                                    buffer->line[displine][(x<<4)+c+8]^=15;
 157.321 +                                        }
 157.322 +                                }
 157.323 +                        }
 157.324 +                        else if (!(tandy_mode&16))
 157.325 +                        {
 157.326 +                                cols[0]=(tandy_col&15)|16;
 157.327 +                                col=(tandy_col&16)?24:16;
 157.328 +                                if (tandy_mode&4)
 157.329 +                                {
 157.330 +                                        cols[1]=col|3;
 157.331 +                                        cols[2]=col|4;
 157.332 +                                        cols[3]=col|7;
 157.333 +                                }
 157.334 +                                else if (tandy_col&32)
 157.335 +                                {
 157.336 +                                        cols[1]=col|3;
 157.337 +                                        cols[2]=col|5;
 157.338 +                                        cols[3]=col|7;
 157.339 +                                }
 157.340 +                                else
 157.341 +                                {
 157.342 +                                        cols[1]=col|2;
 157.343 +                                        cols[2]=col|4;
 157.344 +                                        cols[3]=col|6;
 157.345 +                                }
 157.346 +                                for (x=0;x<crtc[1];x++)
 157.347 +                                {
 157.348 +                                        dat=(tandy_vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|tandy_vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
 157.349 +                                        ma++;
 157.350 +                                        for (c=0;c<8;c++)
 157.351 +                                        {
 157.352 +                                                buffer->line[displine][(x<<4)+(c<<1)+8]=
 157.353 +                                                  buffer->line[displine][(x<<4)+(c<<1)+1+8]=cols[dat>>14];
 157.354 +                                                dat<<=2;
 157.355 +                                        }
 157.356 +                                }
 157.357 +                        }
 157.358 +                        else
 157.359 +                        {
 157.360 +                                cols[0]=0; cols[1]=tandy_array[(tandy_col&tandy_array[1])+16]+16;
 157.361 +                                for (x=0;x<crtc[1];x++)
 157.362 +                                {
 157.363 +                                        dat=(tandy_vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)]<<8)|tandy_vram[((ma<<1)&0x1FFF)+((sc&1)*0x2000)+1];
 157.364 +                                        ma++;
 157.365 +                                        for (c=0;c<16;c++)
 157.366 +                                        {
 157.367 +                                                buffer->line[displine][(x<<4)+c+8]=cols[dat>>15];
 157.368 +                                                dat<<=1;
 157.369 +                                        }
 157.370 +                                }
 157.371 +                        }
 157.372 +                }
 157.373 +                else
 157.374 +                {
 157.375 +                        if (tandy_array[3]&4)
 157.376 +                        {
 157.377 +                                if (tandy_mode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,(tandy_array[2]&0xF)+16);
 157.378 +                                else              hline(buffer,0,displine,(crtc[1]<<4)+16,(tandy_array[2]&0xF)+16);
 157.379 +                        }
 157.380 +                        else
 157.381 +                        {
 157.382 +                                cols[0]=((tandy_mode&0x12)==0x12)?0:(tandy_col&15)+16;
 157.383 +                                if (tandy_mode&1) hline(buffer,0,displine,(crtc[1]<<3)+16,cols[0]);
 157.384 +                                else              hline(buffer,0,displine,(crtc[1]<<4)+16,cols[0]);
 157.385 +                        }
 157.386 +                }
 157.387 +                if (tandy_mode&1) x=(crtc[1]<<3)+16;
 157.388 +                else              x=(crtc[1]<<4)+16;
 157.389 +                if (cga_comp)
 157.390 +                {
 157.391 +                        for (c=0;c<x;c++)
 157.392 +                        {
 157.393 +                                y_buf[(c<<1)&6]=ntsc_col[buffer->line[displine][c]&7][(c<<1)&6]?0x6000:0;
 157.394 +                                y_buf[(c<<1)&6]+=(buffer->line[displine][c]&8)?0x3000:0;
 157.395 +                                i_buf[(c<<1)&6]=y_buf[(c<<1)&6]*i_filt[(c<<1)&6];
 157.396 +                                q_buf[(c<<1)&6]=y_buf[(c<<1)&6]*q_filt[(c<<1)&6];
 157.397 +                                y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
 157.398 +                                i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
 157.399 +                                q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
 157.400 +
 157.401 +                                y_val=y_tot>>10;
 157.402 +                                if (y_val>255) y_val=255;
 157.403 +                                y_val<<=16;
 157.404 +                                i_val=i_tot>>12;
 157.405 +                                if (i_val>39041) i_val=39041;
 157.406 +                                if (i_val<-39041) i_val=-39041;
 157.407 +                                q_val=q_tot>>12;
 157.408 +                                if (q_val>34249) q_val=34249;
 157.409 +                                if (q_val<-34249) q_val=-34249;
 157.410 +
 157.411 +                                r=(y_val+249*i_val+159*q_val)>>16;
 157.412 +                                g=(y_val-70*i_val-166*q_val)>>16;
 157.413 +                                b=(y_val-283*i_val+436*q_val)>>16;
 157.414 +//                                if (r>255) r=255;
 157.415 +//                                if (g>255) g=255;
 157.416 +//                              if (b>255) b=255;
 157.417 +
 157.418 +                                y_buf[((c<<1)&6)+1]=ntsc_col[buffer->line[displine][c]&7][((c<<1)&6)+1]?0x6000:0;
 157.419 +                                y_buf[((c<<1)&6)+1]+=(buffer->line[displine][c]&8)?0x3000:0;
 157.420 +                                i_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*i_filt[((c<<1)&6)+1];
 157.421 +                                q_buf[((c<<1)&6)+1]=y_buf[((c<<1)&6)+1]*q_filt[((c<<1)&6)+1];
 157.422 +                                y_tot=y_buf[0]+y_buf[1]+y_buf[2]+y_buf[3]+y_buf[4]+y_buf[5]+y_buf[6]+y_buf[7];
 157.423 +                                i_tot=i_buf[0]+i_buf[1]+i_buf[2]+i_buf[3]+i_buf[4]+i_buf[5]+i_buf[6]+i_buf[7];
 157.424 +                                q_tot=q_buf[0]+q_buf[1]+q_buf[2]+q_buf[3]+q_buf[4]+q_buf[5]+q_buf[6]+q_buf[7];
 157.425 +
 157.426 +                                y_val=y_tot>>10;
 157.427 +                                if (y_val>255) y_val=255;
 157.428 +                                y_val<<=16;
 157.429 +                                i_val=i_tot>>12;
 157.430 +                                if (i_val>39041) i_val=39041;
 157.431 +                                if (i_val<-39041) i_val=-39041;
 157.432 +                                q_val=q_tot>>12;
 157.433 +                                if (q_val>34249) q_val=34249;
 157.434 +                                if (q_val<-34249) q_val=-34249;
 157.435 +
 157.436 +                                r+=(y_val+249*i_val+159*q_val)>>16;
 157.437 +                                g+=(y_val-70*i_val-166*q_val)>>16;
 157.438 +                                b+=(y_val-283*i_val+436*q_val)>>16;
 157.439 +                                if (r>511) r=511;
 157.440 +                                if (g>511) g=511;
 157.441 +                                if (b>511) b=511;
 157.442 +
 157.443 +                                ((uint32_t *)buffer32->line[displine])[c]=makecol32(r/2,g/2,b/2);
 157.444 +                        }
 157.445 +                }
 157.446 +                sc=oldsc;
 157.447 +                if (vc==crtc[7] && !sc)
 157.448 +                {
 157.449 +                        cgastat|=8;
 157.450 +//                        printf("VSYNC on %i %i\n",vc,sc);
 157.451 +                }
 157.452 +                displine++;
 157.453 +                if (displine>=360) displine=0;
 157.454 +        }
 157.455 +        else
 157.456 +        {
 157.457 +                vidtime+=dispontime;
 157.458 +                if (cgadispon) cgastat&=~1;
 157.459 +                linepos=0;
 157.460 +                if (vsynctime)
 157.461 +                {
 157.462 +                        vsynctime--;
 157.463 +                        if (!vsynctime)
 157.464 +                        {
 157.465 +                                cgastat&=~8;
 157.466 +//                                printf("VSYNC off %i %i\n",vc,sc);
 157.467 +                        }
 157.468 +                }
 157.469 +                if (sc==(crtc[11]&31) || ((crtc[8]&3)==3 && sc==((crtc[11]&31)>>1))) { con=0; coff=1; }
 157.470 +                if (vadj)
 157.471 +                {
 157.472 +                        sc++;
 157.473 +                        sc&=31;
 157.474 +                        ma=maback;
 157.475 +                        vadj--;
 157.476 +                        if (!vadj)
 157.477 +                        {
 157.478 +                                cgadispon=1;
 157.479 +                                ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 157.480 +                                sc=0;
 157.481 +//                                printf("Display on!\n");
 157.482 +                        }
 157.483 +                }
 157.484 +                else if (sc==crtc[9] || ((crtc[8]&3)==3 && sc==(crtc[9]>>1)))
 157.485 +                {
 157.486 +                        maback=ma;
 157.487 +//                        con=0;
 157.488 +//                        coff=0;
 157.489 +                        sc=0;
 157.490 +                        oldvc=vc;
 157.491 +                        vc++;
 157.492 +                        vc&=127;
 157.493 +//                        printf("VC %i %i %i %i  %i\n",vc,crtc[4],crtc[6],crtc[7],cgadispon);
 157.494 +                        if (vc==crtc[6]) cgadispon=0;
 157.495 +                        if (oldvc==crtc[4])
 157.496 +                        {
 157.497 +//                                printf("Display over at %i\n",displine);
 157.498 +                                vc=0;
 157.499 +                                vadj=crtc[5];
 157.500 +                                if (!vadj) cgadispon=1;
 157.501 +                                if (!vadj) ma=maback=(crtc[13]|(crtc[12]<<8))&0x3FFF;
 157.502 +                                if ((crtc[10]&0x60)==0x20) cursoron=0;
 157.503 +                                else                       cursoron=cgablink&16;
 157.504 +//                                printf("CRTC10 %02X %i\n",crtc[10],cursoron);
 157.505 +                        }
 157.506 +                        if (vc==crtc[7])
 157.507 +                        {
 157.508 +                                cgadispon=0;
 157.509 +                                displine=0;
 157.510 +                                vsynctime=16;//(crtc[3]>>4)+1;
 157.511 +//                                printf("Vsynctime %i %02X\n",vsynctime,crtc[3]);
 157.512 +//                                cgastat|=8;
 157.513 +                                if (crtc[7])
 157.514 +                                {
 157.515 +//                                        printf("Lastline %i Firstline %i  %i   %i %i\n",lastline,firstline,lastline-firstline,crtc[1],xsize);
 157.516 +                                        if (tandy_mode&1) x=(crtc[1]<<3)+16;
 157.517 +                                        else              x=(crtc[1]<<4)+16;
 157.518 +                                        lastline++;
 157.519 +                                        if (x!=xsize || (lastline-firstline)!=ysize)
 157.520 +                                        {
 157.521 +                                                xsize=x;
 157.522 +                                                ysize=lastline-firstline;
 157.523 +//                                                printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtc[1]);
 157.524 +                                                if (xsize<64) xsize=656;
 157.525 +                                                if (ysize<32) ysize=200;
 157.526 +                                                updatewindowsize(xsize,(ysize<<1)+16);
 157.527 +                                        }
 157.528 +//                                        printf("Blit %i %i\n",firstline,lastline);
 157.529 +//printf("Xsize is %i\n",xsize);
 157.530 +                                startblit();
 157.531 +                                        if (cga_comp) 
 157.532 +                                           video_blit_memtoscreen(0, firstline-4, 0, (lastline-firstline)+8, xsize, (lastline-firstline)+8);
 157.533 +                                        else          
 157.534 +                                           video_blit_memtoscreen_8(0, firstline-4, xsize, (lastline-firstline)+8);
 157.535 +                                endblit();
 157.536 +                                        frames++;
 157.537 +                                        video_res_x = xsize - 16;
 157.538 +                                        video_res_y = ysize;
 157.539 +                                        if ((tandy_array[3]&0x10) && (tandy_mode&1)) /*320x200x16*/
 157.540 +                                        {
 157.541 +                                                video_res_x /= 2;
 157.542 +                                                video_bpp = 4;
 157.543 +                                        }
 157.544 +                                        else if (tandy_array[3]&0x10) /*160x200x16*/
 157.545 +                                        {
 157.546 +                                                video_res_x /= 4;
 157.547 +                                                video_bpp = 4;
 157.548 +                                        }
 157.549 +                                        else if (tandy_array[3]&0x08) /*640x200x4 - this implementation is a complete guess!*/
 157.550 +                                           video_bpp = 2;
 157.551 +                                        else if (tandy_mode&1)
 157.552 +                                        {
 157.553 +                                                video_res_x /= 8;
 157.554 +                                                video_res_y /= crtc[9] + 1;
 157.555 +                                                video_bpp = 0;
 157.556 +                                        }
 157.557 +                                        else if (!(tandy_mode&2))
 157.558 +                                        {
 157.559 +                                                video_res_x /= 16;
 157.560 +                                                video_res_y /= crtc[9] + 1;
 157.561 +                                                video_bpp = 0;
 157.562 +                                        }
 157.563 +                                        else if (!(tandy_mode&16))
 157.564 +                                        {
 157.565 +                                                video_res_x /= 2;
 157.566 +                                                video_bpp = 2;
 157.567 +                                        }
 157.568 +                                        else
 157.569 +                                           video_bpp = 1;                                                
 157.570 +                                }
 157.571 +                                firstline=1000;
 157.572 +                                lastline=0;
 157.573 +                                cgablink++;
 157.574 +                        }
 157.575 +                }
 157.576 +                else
 157.577 +                {
 157.578 +                        sc++;
 157.579 +                        sc&=31;
 157.580 +                        ma=maback;
 157.581 +                }
 157.582 +                if ((sc==(crtc[10]&31) || ((crtc[8]&3)==3 && sc==((crtc[10]&31)>>1)))) con=1;
 157.583 +        }
 157.584 +}
 157.585 +
 157.586 +int tandy_init()
 157.587 +{
 157.588 +        mem_sethandler(0xb8000, 0x8000, tandy_read, NULL, NULL, tandy_write, NULL, NULL);
 157.589 +        io_sethandler(0x00a0, 0x0002, tandy_in, NULL, NULL, tandy_out, NULL, NULL);
 157.590 +        tandy_memctrl = -1;
 157.591 +        return 0;
 157.592 +}
 157.593 +
 157.594 +GFXCARD vid_tandy =
 157.595 +{
 157.596 +        tandy_init,
 157.597 +        /*IO at 3Cx/3Dx*/
 157.598 +        tandy_out,
 157.599 +        tandy_in,
 157.600 +        /*IO at 3Ax/3Bx*/
 157.601 +        video_out_null,
 157.602 +        video_in_null,
 157.603 +
 157.604 +        tandy_poll,
 157.605 +        tandy_recalctimings,
 157.606 +
 157.607 +        video_write_null,
 157.608 +        video_write_null,
 157.609 +        tandy_write,
 157.610 +
 157.611 +        video_read_null,
 157.612 +        video_read_null,
 157.613 +        tandy_read
 157.614 +};
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/src/vid_tkd8001_ramdac.c	Sun Apr 21 14:54:35 2013 +0100
   158.3 @@ -0,0 +1,64 @@
   158.4 +/*Trident TKD8001 RAMDAC emulation*/
   158.5 +#include "ibm.h"
   158.6 +#include "video.h"
   158.7 +#include "vid_svga.h"
   158.8 +#include "vid_tkd8001_ramdac.h"
   158.9 +
  158.10 +static int tkd8001_state=0;
  158.11 +static uint8_t tkd8001_ctrl;
  158.12 +
  158.13 +void tkd8001_ramdac_out(uint16_t addr, uint8_t val)
  158.14 +{
  158.15 +//        pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc);
  158.16 +        switch (addr)
  158.17 +        {
  158.18 +                case 0x3C6:
  158.19 +                if (tkd8001_state == 4)
  158.20 +                {
  158.21 +                        tkd8001_state = 0;
  158.22 +                        tkd8001_ctrl = val;
  158.23 +                        switch (val>>5)
  158.24 +                        {
  158.25 +                                case 0: case 1: case 2: case 3:
  158.26 +                                bpp = 8;
  158.27 +                                break;
  158.28 +                                case 5:
  158.29 +                                bpp = 15;
  158.30 +                                break;
  158.31 +                                case 6:
  158.32 +                                bpp = 24;
  158.33 +                                break;
  158.34 +                                case 7:
  158.35 +                                bpp = 16;
  158.36 +                                break;
  158.37 +                        }
  158.38 +                        return;
  158.39 +                }
  158.40 +               // tkd8001_state = 0;
  158.41 +                break;
  158.42 +                case 0x3C7: case 0x3C8: case 0x3C9:
  158.43 +                tkd8001_state = 0;
  158.44 +                break;
  158.45 +        }
  158.46 +        svga_out(addr,val);
  158.47 +}
  158.48 +
  158.49 +uint8_t tkd8001_ramdac_in(uint16_t addr)
  158.50 +{
  158.51 +//        pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc);
  158.52 +        switch (addr)
  158.53 +        {
  158.54 +                case 0x3C6:
  158.55 +                if (tkd8001_state == 4)
  158.56 +                {
  158.57 +                        //tkd8001_state = 0;
  158.58 +                        return tkd8001_ctrl;
  158.59 +                }
  158.60 +                tkd8001_state++;
  158.61 +                break;
  158.62 +                case 0x3C7: case 0x3C8: case 0x3C9:
  158.63 +                tkd8001_state = 0;
  158.64 +                break;
  158.65 +        }
  158.66 +        return svga_in(addr);
  158.67 +}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/src/vid_tkd8001_ramdac.h	Sun Apr 21 14:54:35 2013 +0100
   159.3 @@ -0,0 +1,2 @@
   159.4 +void tkd8001_ramdac_out(uint16_t addr, uint8_t val);
   159.5 +uint8_t tkd8001_ramdac_in(uint16_t addr);
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/src/vid_tvga.c	Sun Apr 21 14:54:35 2013 +0100
   160.3 @@ -0,0 +1,199 @@
   160.4 +/*Trident TVGA (8900D) emulation*/
   160.5 +#include "ibm.h"
   160.6 +#include "video.h"
   160.7 +#include "vid_svga.h"
   160.8 +#include "vid_tkd8001_ramdac.h"
   160.9 +
  160.10 +uint8_t trident3d8,trident3d9;
  160.11 +int tridentoldmode;
  160.12 +uint8_t tridentoldctrl2,tridentnewctrl2;
  160.13 +uint8_t tridentdac;
  160.14 +
  160.15 +void tvga_out(uint16_t addr, uint8_t val)
  160.16 +{
  160.17 +        uint8_t old;
  160.18 +
  160.19 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
  160.20 +
  160.21 +        switch (addr)
  160.22 +        {
  160.23 +                case 0x3C5:
  160.24 +                switch (seqaddr&0xF)
  160.25 +                {
  160.26 +                        case 0xB: tridentoldmode=1; break;
  160.27 +                        case 0xC: if (seqregs[0xE]&0x80) seqregs[0xC]=val; break;
  160.28 +                        case 0xD: if (tridentoldmode) { tridentoldctrl2=val; rowdbl=val&0x10; } else tridentnewctrl2=val; break;
  160.29 +                        case 0xE:
  160.30 +                        seqregs[0xE]=val^2;
  160.31 +                        svgawbank=(seqregs[0xE]&0xF)*65536;
  160.32 +                        if (!(gdcreg[0xF]&1)) svgarbank=svgawbank;
  160.33 +                        return;
  160.34 +                }
  160.35 +                break;
  160.36 +
  160.37 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
  160.38 +                tkd8001_ramdac_out(addr,val);
  160.39 +                return;
  160.40 +
  160.41 +                case 0x3CF:
  160.42 +                switch (gdcaddr&15)
  160.43 +                {
  160.44 +                        case 0xE:
  160.45 +                        gdcreg[0xE]=val^2;
  160.46 +                        if ((gdcreg[0xF]&1)==1)
  160.47 +                           svgarbank=(gdcreg[0xE]&0xF)*65536;
  160.48 +                        break;
  160.49 +                        case 0xF:
  160.50 +                        if (val&1) svgarbank=(gdcreg[0xE] &0xF)*65536;
  160.51 +                        else       svgarbank=(seqregs[0xE]&0xF)*65536;
  160.52 +                        svgawbank=(seqregs[0xE]&0xF)*65536;
  160.53 +                        break;
  160.54 +                }
  160.55 +                break;
  160.56 +                case 0x3D4:
  160.57 +                crtcreg=val&63;
  160.58 +                return;
  160.59 +                case 0x3D5:
  160.60 +                if (crtcreg <= 7 && crtc[0x11] & 0x80) return;
  160.61 +                old=crtc[crtcreg];
  160.62 +                crtc[crtcreg]=val;
  160.63 +                //if (crtcreg!=0xE && crtcreg!=0xF) pclog("CRTC R%02X = %02X\n",crtcreg,val);
  160.64 +                if (old!=val)
  160.65 +                {
  160.66 +                        if (crtcreg<0xE || crtcreg>0x10)
  160.67 +                        {
  160.68 +                                fullchange=changeframecount;
  160.69 +                                svga_recalctimings();
  160.70 +                        }
  160.71 +                }
  160.72 +                return;
  160.73 +                case 0x3D8:
  160.74 +                trident3d8=val;
  160.75 +                if (gdcreg[0xF]&4)
  160.76 +                {
  160.77 +                        svgawbank=(val&0x1F)*65536;
  160.78 +//                                pclog("SVGAWBANK 3D8 %08X %04X:%04X\n",svgawbank,CS,pc);
  160.79 +                        if (!(gdcreg[0xF]&1))
  160.80 +                        {
  160.81 +                                svgarbank=(val&0x1F)*65536;
  160.82 +//                                        pclog("SVGARBANK 3D8 %08X %04X:%04X\n",svgarbank,CS,pc);
  160.83 +                        }
  160.84 +                }
  160.85 +                return;
  160.86 +                case 0x3D9:
  160.87 +                trident3d9=val;
  160.88 +                if ((gdcreg[0xF]&5)==5)
  160.89 +                {
  160.90 +                        svgarbank=(val&0x1F)*65536;
  160.91 +//                                pclog("SVGARBANK 3D9 %08X %04X:%04X\n",svgarbank,CS,pc);
  160.92 +                }
  160.93 +                return;
  160.94 +        }
  160.95 +        svga_out(addr,val);
  160.96 +}
  160.97 +
  160.98 +uint8_t tvga_in(uint16_t addr)
  160.99 +{
 160.100 +        uint8_t temp;
 160.101 +        
 160.102 +        if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga_miscout&1)) addr ^= 0x60;
 160.103 +        
 160.104 +        switch (addr)
 160.105 +        {
 160.106 +                case 0x3C5:
 160.107 +                if ((seqaddr&0xF)==0xB)
 160.108 +                {
 160.109 +//                        printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
 160.110 +                        tridentoldmode=0;
 160.111 +                        return 0x33; /*TVGA8900D*/
 160.112 +                }
 160.113 +                if ((seqaddr&0xF)==0xC)
 160.114 +                {
 160.115 +//                        printf("Read Trident Power Up 1 %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
 160.116 +//                        return 0x20; /*2 DRAM banks*/
 160.117 +                }
 160.118 +                if ((seqaddr&0xF)==0xD)
 160.119 +                {
 160.120 +                        if (tridentoldmode) return tridentoldctrl2;
 160.121 +                        return tridentnewctrl2;
 160.122 +                }
 160.123 +                break;
 160.124 +                case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
 160.125 +                return tkd8001_ramdac_in(addr);
 160.126 +                case 0x3CD: /*Banking*/
 160.127 +                return svgaseg;
 160.128 +                case 0x3D4:
 160.129 +                return crtcreg;
 160.130 +                case 0x3D5:
 160.131 +                return crtc[crtcreg];
 160.132 +        }
 160.133 +        return svga_in(addr);
 160.134 +}
 160.135 +
 160.136 +void tvga_recalctimings()
 160.137 +{
 160.138 +        if (!svga_rowoffset) svga_rowoffset=0x100; /*This is the only sensible way I can see this being handled,
 160.139 +                                                     given that TVGA8900D has no overflow bits.
 160.140 +                                                     Some sort of overflow is required for 320x200x24 and 1024x768x16*/
 160.141 +
 160.142 +        if ((crtc[0x1E]&0xA0)==0xA0) svga_ma|=0x10000;
 160.143 +        if ((crtc[0x27]&0x01)==0x01) svga_ma|=0x20000;
 160.144 +        if ((crtc[0x27]&0x02)==0x02) svga_ma|=0x40000;
 160.145 +        
 160.146 +        if (tridentoldctrl2 & 0x10)
 160.147 +        {
 160.148 +                svga_rowoffset<<=1;
 160.149 +                svga_ma<<=1;
 160.150 +        }
 160.151 +        if (tridentoldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/
 160.152 +           svga_lowres=0;
 160.153 +           
 160.154 +        if (gdcreg[0xF] & 8)
 160.155 +        {
 160.156 +                svga_htotal<<=1;
 160.157 +                svga_hdisp<<=1;
 160.158 +        }
 160.159 +        svga_interlace = crtc[0x1E] & 4;
 160.160 +        if (svga_interlace)
 160.161 +           svga_rowoffset >>= 1;
 160.162 +        
 160.163 +        switch (((svga_miscout>>2)&3) | ((tridentnewctrl2<<2)&4))
 160.164 +        {
 160.165 +                case 2: svga_clock = cpuclock/44900000.0; break;
 160.166 +                case 3: svga_clock = cpuclock/36000000.0; break;
 160.167 +                case 4: svga_clock = cpuclock/57272000.0; break;
 160.168 +                case 5: svga_clock = cpuclock/65000000.0; break;
 160.169 +                case 6: svga_clock = cpuclock/50350000.0; break;
 160.170 +                case 7: svga_clock = cpuclock/40000000.0; break;
 160.171 +        }
 160.172 +}
 160.173 +
 160.174 +int tvga_init()
 160.175 +{
 160.176 +        svga_recalctimings_ex = tvga_recalctimings;
 160.177 +        svga_vram_limit = 1 << 20; /*1mb - chip supports 2mb, but drivers are buggy*/
 160.178 +        vrammask = 0xfffff;
 160.179 +        return svga_init();
 160.180 +}
 160.181 +
 160.182 +GFXCARD vid_tvga =
 160.183 +{
 160.184 +        tvga_init,
 160.185 +        /*IO at 3Cx/3Dx*/
 160.186 +        tvga_out,
 160.187 +        tvga_in,
 160.188 +        /*IO at 3Ax/3Bx*/
 160.189 +        video_out_null,
 160.190 +        video_in_null,
 160.191 +        
 160.192 +        svga_poll,
 160.193 +        svga_recalctimings,
 160.194 +        
 160.195 +        svga_write,
 160.196 +        video_write_null,
 160.197 +        video_write_null,
 160.198 +        
 160.199 +        svga_read,
 160.200 +        video_read_null,
 160.201 +        video_read_null
 160.202 +};
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/src/vid_unk_ramdac.c	Sun Apr 21 14:54:35 2013 +0100
   161.3 @@ -0,0 +1,66 @@
   161.4 +/*It is unknown exactly what RAMDAC this is
   161.5 +  It is possibly a Sierra 1502x
   161.6 +  It's addressed by the TLIVESA1 driver for ET4000*/
   161.7 +#include "ibm.h"
   161.8 +#include "video.h"
   161.9 +#include "vid_svga.h"
  161.10 +#include "vid_unk_ramdac.h"
  161.11 +
  161.12 +static int unk_state=0;
  161.13 +static uint8_t unk_ctrl;
  161.14 +
  161.15 +void unk_ramdac_out(uint16_t addr, uint8_t val)
  161.16 +{
  161.17 +        //pclog("OUT RAMDAC %04X %02X\n",addr,val);
  161.18 +        switch (addr)
  161.19 +        {
  161.20 +                case 0x3C6:
  161.21 +                if (unk_state == 4)
  161.22 +                {
  161.23 +                        unk_state = 0;
  161.24 +                        unk_ctrl = val;
  161.25 +                        switch ((val&1)|((val&0xE0)>>4))
  161.26 +                        {
  161.27 +                                case 0: case 1: case 2: case 3:
  161.28 +                                bpp = 8;
  161.29 +                                break;
  161.30 +                                case 6: case 7:
  161.31 +                                bpp = 24;
  161.32 +                                break;
  161.33 +                                case 8: case 9: case 0xA: case 0xB:
  161.34 +                                bpp = 15;
  161.35 +                                break;
  161.36 +                                case 0xC: case 0xD: case 0xE: case 0xF:
  161.37 +                                bpp = 16;
  161.38 +                                break;
  161.39 +                        }
  161.40 +                        return;
  161.41 +                }
  161.42 +                unk_state = 0;
  161.43 +                break;
  161.44 +                case 0x3C7: case 0x3C8: case 0x3C9:
  161.45 +                unk_state = 0;
  161.46 +                break;
  161.47 +        }
  161.48 +        svga_out(addr,val);
  161.49 +}
  161.50 +
  161.51 +uint8_t unk_ramdac_in(uint16_t addr)
  161.52 +{
  161.53 +        //pclog("IN RAMDAC %04X\n",addr);
  161.54 +        switch (addr)
  161.55 +        {
  161.56 +                case 0x3C6:
  161.57 +                if (unk_state == 4)
  161.58 +                {
  161.59 +                        unk_state = 0;
  161.60 +                        return unk_ctrl;
  161.61 +                }
  161.62 +                unk_state++;
  161.63 +                break;
  161.64 +                case 0x3C7: case 0x3C8: case 0x3C9:
  161.65 +                unk_state = 0;
  161.66 +                break;
  161.67 +        }
  161.68 +        return svga_in(addr);
  161.69 +}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/src/vid_unk_ramdac.h	Sun Apr 21 14:54:35 2013 +0100
   162.3 @@ -0,0 +1,2 @@
   162.4 +void unk_ramdac_out(uint16_t addr, uint8_t val);
   162.5 +uint8_t unk_ramdac_in(uint16_t addr);
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/src/video.c	Sun Apr 21 14:54:35 2013 +0100
   163.3 @@ -0,0 +1,494 @@
   163.4 +#include <stdio.h>
   163.5 +#include <math.h>
   163.6 +#include "ibm.h"
   163.7 +#include "video.h"
   163.8 +#include "vid_svga.h"
   163.9 +#include "io.h"
  163.10 +#include "cpu.h"
  163.11 +
  163.12 +/*Video timing settings -
  163.13 +
  163.14 +8-bit - 1mb/sec
  163.15 +        B = 8 ISA clocks
  163.16 +        W = 16 ISA clocks
  163.17 +        L = 32 ISA clocks
  163.18 +        
  163.19 +Slow 16-bit - 2mb/sec
  163.20 +        B = 6 ISA clocks
  163.21 +        W = 8 ISA clocks
  163.22 +        L = 16 ISA clocks
  163.23 +
  163.24 +Fast 16-bit - 4mb/sec
  163.25 +        B = 3 ISA clocks
  163.26 +        W = 3 ISA clocks
  163.27 +        L = 6 ISA clocks
  163.28 +        
  163.29 +Slow VLB/PCI - 8mb/sec (ish)
  163.30 +        B = 4 bus clocks
  163.31 +        W = 8 bus clocks
  163.32 +        L = 16 bus clocks
  163.33 +        
  163.34 +Mid VLB/PCI -
  163.35 +        B = 4 bus clocks
  163.36 +        W = 5 bus clocks
  163.37 +        L = 10 bus clocks
  163.38 +        
  163.39 +Fast VLB/PCI -
  163.40 +        B = 3 bus clocks
  163.41 +        W = 3 bus clocks
  163.42 +        L = 4 bus clocks
  163.43 +*/
  163.44 +
  163.45 +enum
  163.46 +{
  163.47 +        VIDEO_ISA = 0,
  163.48 +        VIDEO_BUS
  163.49 +};
  163.50 +
  163.51 +int video_speed = 0;
  163.52 +int video_timing[6][4] =
  163.53 +{
  163.54 +        {VIDEO_ISA, 8, 16, 32},
  163.55 +        {VIDEO_ISA, 6,  8, 16},
  163.56 +        {VIDEO_ISA, 3,  3,  6},
  163.57 +        {VIDEO_BUS, 4,  8, 16},
  163.58 +        {VIDEO_BUS, 4,  5, 10},
  163.59 +        {VIDEO_BUS, 3,  3,  4}
  163.60 +};
  163.61 +
  163.62 +void video_updatetiming()
  163.63 +{
  163.64 +        if (video_timing[video_speed][0] == VIDEO_ISA)
  163.65 +        {
  163.66 +                video_timing_b = (int)(isa_timing * video_timing[video_speed][1]);
  163.67 +                video_timing_w = (int)(isa_timing * video_timing[video_speed][2]);
  163.68 +                video_timing_l = (int)(isa_timing * video_timing[video_speed][3]);
  163.69 +        }
  163.70 +        else
  163.71 +        {
  163.72 +                video_timing_b = (int)(bus_timing * video_timing[video_speed][1]);
  163.73 +                video_timing_w = (int)(bus_timing * video_timing[video_speed][2]);
  163.74 +                video_timing_l = (int)(bus_timing * video_timing[video_speed][3]);
  163.75 +        }
  163.76 +        if (cpu_16bitbus)
  163.77 +           video_timing_l = video_timing_w * 2;
  163.78 +}
  163.79 +
  163.80 +int video_timing_b, video_timing_w, video_timing_l;
  163.81 +
  163.82 +int video_res_x, video_res_y, video_bpp;
  163.83 +
  163.84 +void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h);
  163.85 +void (*video_blit_memtoscreen_8)(int x, int y, int w, int h);
  163.86 +
  163.87 +void (*video_out)     (uint16_t addr, uint8_t val);
  163.88 +void (*video_mono_out)(uint16_t addr, uint8_t val);
  163.89 +uint8_t (*video_in)     (uint16_t addr);
  163.90 +uint8_t (*video_mono_in)(uint16_t addr);
  163.91 +
  163.92 +void (*video_write_a000)(uint32_t addr, uint8_t val);
  163.93 +void (*video_write_b000)(uint32_t addr, uint8_t val);
  163.94 +void (*video_write_b800)(uint32_t addr, uint8_t val);
  163.95 +
  163.96 +void (*video_write_a000_w)(uint32_t addr, uint16_t val);
  163.97 +void (*video_write_a000_l)(uint32_t addr, uint32_t val);
  163.98 +
  163.99 +uint8_t (*video_read_a000)(uint32_t addr);
 163.100 +uint8_t (*video_read_b000)(uint32_t addr);
 163.101 +uint8_t (*video_read_b800)(uint32_t addr);
 163.102 +
 163.103 +void (*video_recalctimings)();
 163.104 +
 163.105 +void video_out_null(uint16_t addr, uint8_t val)
 163.106 +{
 163.107 +}
 163.108 +
 163.109 +uint8_t video_in_null(uint16_t addr)
 163.110 +{
 163.111 +        return 0xFF;
 163.112 +}
 163.113 +
 163.114 +void video_write_null(uint32_t addr, uint8_t val)
 163.115 +{
 163.116 +}
 163.117 +
 163.118 +uint8_t video_read_null(uint32_t addr)
 163.119 +{
 163.120 +        return 0xff;
 163.121 +}
 163.122 +
 163.123 +void video_load(GFXCARD g)
 163.124 +{
 163.125 +        io_sethandler(0x03a0, 0x0020, g.mono_in, NULL, NULL, g.mono_out, NULL, NULL);
 163.126 +        io_sethandler(0x03c0, 0x0020, g.in,      NULL, NULL, g.out,      NULL, NULL);        
 163.127 +        
 163.128 +        video_out      = g.out;
 163.129 +        video_in       = g.in;
 163.130 +        video_mono_out = g.mono_out;
 163.131 +        video_mono_in  = g.mono_in;
 163.132 +        
 163.133 +        pollvideo = g.poll;
 163.134 +        video_recalctimings = g.recalctimings;
 163.135 +        
 163.136 +        video_write_a000 = g.write_a000;
 163.137 +        video_write_b000 = g.write_b000;
 163.138 +        video_write_b800 = g.write_b800;
 163.139 +
 163.140 +        video_read_a000  = g.read_a000;
 163.141 +        video_read_b000  = g.read_b000;
 163.142 +        video_read_b800  = g.read_b800;
 163.143 +        
 163.144 +        video_write_a000_w = video_write_a000_l = NULL;
 163.145 +        
 163.146 +        g.init();
 163.147 +}
 163.148 +
 163.149 +void video_init()
 163.150 +{
 163.151 +        pclog("Video_init %i %i\n",romset,gfxcard);
 163.152 +
 163.153 +        switch (romset)
 163.154 +        {
 163.155 +                case ROM_TANDY:
 163.156 +                video_load(vid_tandy);
 163.157 +                return;
 163.158 +
 163.159 +                case ROM_PC1512:
 163.160 +                video_load(vid_pc1512);
 163.161 +                return;
 163.162 +                
 163.163 +                case ROM_PC1640:
 163.164 +                video_load(vid_pc1640);
 163.165 +                return;
 163.166 +                
 163.167 +                case ROM_PC200:
 163.168 +                video_load(vid_pc200);
 163.169 +                return;
 163.170 +                
 163.171 +                case ROM_OLIM24:
 163.172 +                video_load(vid_m24);
 163.173 +                return;
 163.174 +
 163.175 +                case ROM_PC2086:
 163.176 +                case ROM_PC3086:
 163.177 +                case ROM_MEGAPC:
 163.178 +                video_load(vid_paradise);
 163.179 +                return;
 163.180 +                        
 163.181 +                case ROM_ACER386:
 163.182 +                video_load(vid_oti067);
 163.183 +                return;
 163.184 +        }
 163.185 +        switch (gfxcard)
 163.186 +        {
 163.187 +                case GFX_MDA:
 163.188 +                video_load(vid_mda);
 163.189 +                break;
 163.190 +
 163.191 +                case GFX_HERCULES:
 163.192 +                video_load(vid_hercules);
 163.193 +                break;
 163.194 +                
 163.195 +                case GFX_CGA:
 163.196 +                video_load(vid_cga);
 163.197 +                break;
 163.198 +                
 163.199 +                case GFX_EGA:
 163.200 +                video_load(vid_ega);
 163.201 +                break;
 163.202 +                
 163.203 +                case GFX_TVGA:
 163.204 +                video_load(vid_tvga);
 163.205 +                break;
 163.206 +                
 163.207 +                case GFX_ET4000:
 163.208 +                video_load(vid_et4000);
 163.209 +                break;
 163.210 +                
 163.211 +                case GFX_ET4000W32:
 163.212 +                video_load(vid_et4000w32p);
 163.213 +                break;
 163.214 +
 163.215 +                case GFX_BAHAMAS64:
 163.216 +                video_load(vid_s3);
 163.217 +                break;
 163.218 +
 163.219 +                case GFX_N9_9FX:
 163.220 +                video_load(vid_s3);
 163.221 +                break;
 163.222 +                
 163.223 +                case GFX_STEALTH64:
 163.224 +                video_load(vid_s3);
 163.225 +                break;
 163.226 +                
 163.227 +                default:
 163.228 +                fatal("Bad gfx card %i\n",gfxcard);
 163.229 +        }
 163.230 +}
 163.231 +
 163.232 +uint32_t cga32[256];
 163.233 +
 163.234 +BITMAP *buffer,*vbuf;//,*vbuf2;
 163.235 +BITMAP *buffer32;
 163.236 +int speshul=0;
 163.237 +
 163.238 +uint8_t fontdat[256][8];
 163.239 +uint8_t fontdatm[256][16];
 163.240 +
 163.241 +float dispontime,dispofftime,disptime;
 163.242 +int svgaon;
 163.243 +uint8_t cgamode=1,cgastat,cgacol=7,ocgamode;
 163.244 +int linepos=0;
 163.245 +int output;
 163.246 +uint8_t *vram,*ram;
 163.247 +
 163.248 +int cgadispon=0;
 163.249 +int cgablink;
 163.250 +
 163.251 +uint8_t port3de,port3dd,port3df;
 163.252 +
 163.253 +uint8_t crtc[128],crtcreg;
 163.254 +uint8_t crtcmask[128]={0xFF,0xFF,0xFF,0xFF,0x7F,0x1F,0x7F,0x7F,0xF3,0x1F,0x7F,0x1F,0x3F,0xFF,0x3F,0xFF,0xFF,0xFF};
 163.255 +uint8_t charbuffer[256];
 163.256 +int crtcams[64]={0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1};
 163.257 +int nmi=0;
 163.258 +
 163.259 +
 163.260 +int xsize=1,ysize=1;
 163.261 +int firstline=1000,lastline=0;
 163.262 +
 163.263 +int ntsc_col[8][8]=
 163.264 +{
 163.265 +        {0,0,0,0,0,0,0,0}, /*Black*/
 163.266 +        {0,0,1,1,1,1,0,0}, /*Blue*/
 163.267 +        {1,0,0,0,0,1,1,1}, /*Green*/
 163.268 +        {0,0,0,0,1,1,1,1}, /*Cyan*/
 163.269 +        {1,1,1,1,0,0,0,0}, /*Red*/
 163.270 +        {0,1,1,1,1,0,0,0}, /*Magenta*/
 163.271 +        {1,1,0,0,0,0,1,1}, /*Yellow*/
 163.272 +        {1,1,1,1,1,1,1,1}  /*White*/
 163.273 +};
 163.274 +
 163.275 +
 163.276 +extern int fullchange;
 163.277 +
 163.278 +extern uint32_t vrammask;
 163.279 +
 163.280 +
 163.281 +int mdacols[256][2][2];
 163.282 +uint8_t gdcreg[16];
 163.283 +
 163.284 +
 163.285 +int cga4pal[8][4]=
 163.286 +{
 163.287 +        {0,2,4,6},{0,3,5,7},{0,3,4,7},{0,3,4,7},
 163.288 +        {0,10,12,14},{0,11,13,15},{0,11,12,15},{0,11,12,15}
 163.289 +};
 163.290 +
 163.291 +
 163.292 +PALETTE cgapal=
 163.293 +{
 163.294 +        {0,0,0},{0,42,0},{42,0,0},{42,21,0},
 163.295 +        {0,0,0},{0,42,42},{42,0,42},{42,42,42},
 163.296 +        {0,0,0},{21,63,21},{63,21,21},{63,63,21},
 163.297 +        {0,0,0},{21,63,63},{63,21,63},{63,63,63},
 163.298 +
 163.299 +        {0,0,0},{0,0,42},{0,42,0},{0,42,42},
 163.300 +        {42,0,0},{42,0,42},{42,21,00},{42,42,42},
 163.301 +        {21,21,21},{21,21,63},{21,63,21},{21,63,63},
 163.302 +        {63,21,21},{63,21,63},{63,63,21},{63,63,63},
 163.303 +
 163.304 +        {0,0,0},{0,21,0},{0,0,42},{0,42,42},
 163.305 +        {42,0,21},{21,10,21},{42,0,42},{42,0,63},
 163.306 +        {21,21,21},{21,63,21},{42,21,42},{21,63,63},
 163.307 +        {63,0,0},{42,42,0},{63,21,42},{41,41,41},
 163.308 +        
 163.309 +        {0,0,0},{0,42,42},{42,0,0},{42,42,42},
 163.310 +        {0,0,0},{0,42,42},{42,0,0},{42,42,42},
 163.311 +        {0,0,0},{0,63,63},{63,0,0},{63,63,63},
 163.312 +        {0,0,0},{0,63,63},{63,0,0},{63,63,63},
 163.313 +};
 163.314 +
 163.315 +void loadfont(char *s, int format)
 163.316 +{
 163.317 +        FILE *f=romfopen(s,"rb");
 163.318 +        int c,d;
 163.319 +        if (!f)
 163.320 +           return;
 163.321 +
 163.322 +        if (!format)
 163.323 +        {
 163.324 +                for (c=0;c<256;c++)
 163.325 +                {
 163.326 +                        for (d=0;d<8;d++)
 163.327 +                        {
 163.328 +                                fontdatm[c][d]=getc(f);
 163.329 +                        }
 163.330 +                }
 163.331 +                for (c=0;c<256;c++)
 163.332 +                {
 163.333 +                        for (d=0;d<8;d++)
 163.334 +                        {
 163.335 +                                fontdatm[c][d+8]=getc(f);
 163.336 +                        }
 163.337 +                }
 163.338 +                fseek(f,4096+2048,SEEK_SET);
 163.339 +                for (c=0;c<256;c++)
 163.340 +                {
 163.341 +                        for (d=0;d<8;d++)
 163.342 +                        {
 163.343 +                                fontdat[c][d]=getc(f);
 163.344 +                        }
 163.345 +                }
 163.346 +        }
 163.347 +        else if (format == 1)
 163.348 +        {
 163.349 +                for (c=0;c<256;c++)
 163.350 +                {
 163.351 +                        for (d=0;d<8;d++)
 163.352 +                        {
 163.353 +                                fontdatm[c][d]=getc(f);
 163.354 +                        }
 163.355 +                }
 163.356 +                for (c=0;c<256;c++)
 163.357 +                {
 163.358 +                        for (d=0;d<8;d++)
 163.359 +                        {
 163.360 +                                fontdatm[c][d+8]=getc(f);
 163.361 +                        }
 163.362 +                }
 163.363 +                fseek(f, 4096, SEEK_SET);
 163.364 +                for (c=0;c<256;c++)
 163.365 +                {
 163.366 +                        for (d=0;d<8;d++)
 163.367 +                        {
 163.368 +                                fontdat[c][d]=getc(f);
 163.369 +                        }
 163.370 +                        for (d=0;d<8;d++) getc(f);                
 163.371 +                }
 163.372 +        }
 163.373 +        else
 163.374 +        {
 163.375 +                for (c=0;c<256;c++)
 163.376 +                {
 163.377 +                        for (d=0;d<8;d++)
 163.378 +                        {
 163.379 +                                fontdat[c][d]=getc(f);
 163.380 +                        }
 163.381 +                }
 163.382 +        }
 163.383 +        fclose(f);
 163.384 +}
 163.385 +
 163.386 +
 163.387 +void drawscreen()
 163.388 +{
 163.389 +//        printf("Drawscreen %i %i %i %i\n",gfxcard,MDA,EGA,TANDY);
 163.390 +//        if (EGA) drawscreenega(buffer,vbuf);
 163.391 +/*        else if (MDA) {}//drawscreenmda();
 163.392 +        else if (TANDY)
 163.393 +        {
 163.394 +                if ((cgamode&3)==3 || array[3]&0x10) drawscreentandy(tandyvram);
 163.395 +                else                drawscreencga(tandyvram);
 163.396 +        }*/
 163.397 +//        else            drawscreencga(&vram[0x8000]);
 163.398 +}
 163.399 +
 163.400 +PALETTE comppal=
 163.401 +{
 163.402 +        {0,0,0},{0,21,0},{0,0,42},{0,42,42},
 163.403 +        {42,0,21},{21,10,21},{42,0,42},{42,0,63},
 163.404 +        {21,21,21},{21,63,21},{42,21,42},{21,63,31},
 163.405 +        {63,0,0},{42,42,0},{63,21,42},{41,41,41}
 163.406 +};
 163.407 +
 163.408 +void initvideo()
 163.409 +{
 163.410 +        int c,d;
 163.411 +//        set_color_depth(desktop_color_depth());
 163.412 +//        if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,2048,2048,0,0))
 163.413 +//           set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0);
 163.414 +//        vbuf=create_video_bitmap(1280+32,1024+32);
 163.415 +//        set_color_depth(32);
 163.416 +        buffer32=create_bitmap(2048,2048);
 163.417 +//        set_color_depth(8);
 163.418 +        buffer=create_bitmap(2048,2048);
 163.419 +//        set_color_depth(32);
 163.420 +        for (c=0;c<64;c++)
 163.421 +        {
 163.422 +                cgapal[c+64].r=(((c&4)?2:0)|((c&0x10)?1:0))*21;
 163.423 +                cgapal[c+64].g=(((c&2)?2:0)|((c&0x10)?1:0))*21;
 163.424 +                cgapal[c+64].b=(((c&1)?2:0)|((c&0x10)?1:0))*21;
 163.425 +                if ((c&0x17)==6) cgapal[c+64].g>>=1;
 163.426 +        }
 163.427 +        for (c=0;c<64;c++)
 163.428 +        {
 163.429 +                cgapal[c+128].r=(((c&4)?2:0)|((c&0x20)?1:0))*21;
 163.430 +                cgapal[c+128].g=(((c&2)?2:0)|((c&0x10)?1:0))*21;
 163.431 +                cgapal[c+128].b=(((c&1)?2:0)|((c&0x08)?1:0))*21;
 163.432 +        }
 163.433 +        for (c=0;c<256;c++) cga32[c]=makecol(cgapal[c].r<<2,cgapal[c].g<<2,cgapal[c].b<<2);
 163.434 +//        for (c=0;c<16;c++) cgapal[c+192]=comppal[c];
 163.435 +//        set_palette(cgapal);
 163.436 +        if (MDA && !TANDY && !AMSTRAD && romset!=ROM_PC200) updatewindowsize(720,350);
 163.437 +        else                                                updatewindowsize(656,416);
 163.438 +        for (c=17;c<64;c++) crtcmask[c]=0xFF;
 163.439 +}
 163.440 +
 163.441 +void resetvideo()
 163.442 +{
 163.443 +        int c;
 163.444 +        if (MDA && !TANDY && !AMSTRAD && romset!=ROM_PC200) updatewindowsize(720,350);
 163.445 +        else                                                updatewindowsize(656,416);
 163.446 +        cgastat=0;
 163.447 +        set_palette(cgapal);
 163.448 +
 163.449 +        for (c=18;c<64;c++) crtcmask[c]=0xFF;
 163.450 +        crtc[0]=0x38;
 163.451 +        crtc[1]=0x28;
 163.452 +//        crtc[3]=0xFA;
 163.453 +        crtc[4]=0x7F;
 163.454 +        crtc[5]=0x06;
 163.455 +        crtc[6]=0x64;
 163.456 +        crtc[7]=0x70;
 163.457 +        crtc[8]=0x02;
 163.458 +        crtc[9]=1;
 163.459 +
 163.460 +        cgacol=7;
 163.461 +        for (c=0;c<256;c++)
 163.462 +        {
 163.463 +                mdacols[c][0][0]=mdacols[c][1][0]=mdacols[c][1][1]=16;
 163.464 +                if (c&8) mdacols[c][0][1]=15+16;
 163.465 +                else     mdacols[c][0][1]=7+16;
 163.466 +        }
 163.467 +        mdacols[0x70][0][1]=16;
 163.468 +        mdacols[0x70][0][0]=mdacols[0x70][1][0]=mdacols[0x70][1][1]=16+15;
 163.469 +        mdacols[0xF0][0][1]=16;
 163.470 +        mdacols[0xF0][0][0]=mdacols[0xF0][1][0]=mdacols[0xF0][1][1]=16+15;
 163.471 +        mdacols[0x78][0][1]=16+7;
 163.472 +        mdacols[0x78][0][0]=mdacols[0x78][1][0]=mdacols[0x78][1][1]=16+15;
 163.473 +        mdacols[0xF8][0][1]=16+7;
 163.474 +        mdacols[0xF8][0][0]=mdacols[0xF8][1][0]=mdacols[0xF8][1][1]=16+15;
 163.475 +        mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
 163.476 +        mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
 163.477 +        mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
 163.478 +        mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
 163.479 +/*        switch (gfxcard)
 163.480 +        {
 163.481 +                case GFX_CGA: pollvideo=pollcga; break;
 163.482 +                case GFX_MDA:
 163.483 +                case GFX_HERCULES: pollvideo=pollmda; break;
 163.484 +        }
 163.485 +        if (TANDY) pollvideo=polltandy;
 163.486 +        if (EGA) pollvideo=pollega;
 163.487 +        if (romset==ROM_PC1512 || romset==ROM_PC200) pollvideo=pollcga;*/
 163.488 +//        tandyvram=&ram[0x9C000];
 163.489 +//        printf("Tandy VRAM %08X\n",tandyvram);
 163.490 +//        tandyb8000=&ram[0x9C000];
 163.491 +}
 163.492 +
 163.493 +void closevideo()
 163.494 +{
 163.495 +        destroy_bitmap(buffer);
 163.496 +        destroy_bitmap(vbuf);
 163.497 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/src/video.h	Sun Apr 21 14:54:35 2013 +0100
   164.3 @@ -0,0 +1,150 @@
   164.4 +extern int egareads,egawrites;
   164.5 +
   164.6 +extern int bpp;
   164.7 +extern uint8_t svgaseg,svgaseg2;
   164.8 +
   164.9 +extern uint8_t crtcreg;
  164.10 +extern uint8_t crtc[128];
  164.11 +extern uint8_t crtcmask[128];
  164.12 +extern uint8_t gdcreg[16];
  164.13 +extern int gdcaddr;
  164.14 +extern uint8_t attrregs[32];
  164.15 +extern int attraddr,attrff;
  164.16 +extern uint8_t seqregs[32];
  164.17 +extern int seqaddr;
  164.18 +extern int svgaon;
  164.19 +
  164.20 +extern uint8_t cgamode,cgacol,cgastat;
  164.21 +extern int egapal[16];
  164.22 +
  164.23 +extern int scrblank;
  164.24 +
  164.25 +extern uint8_t writemask,charset;
  164.26 +extern int charseta,charsetb;
  164.27 +extern uint8_t colourcompare,colournocare;
  164.28 +extern int readplane,readmode,writemode;
  164.29 +
  164.30 +extern int vidclock;
  164.31 +extern int vres;
  164.32 +
  164.33 +extern uint32_t *pallook,pallook16[256],pallook64[256],pallook256[256];
  164.34 +
  164.35 +extern int fullchange;
  164.36 +extern int changeframecount;
  164.37 +
  164.38 +extern int firstline,lastline;
  164.39 +extern int ega_hdisp,ega_rowoffset,ega_split,ega_dispend,ega_vsyncstart,ega_vtotal;
  164.40 +extern float dispontime,dispofftime,disptime;
  164.41 +
  164.42 +extern void (*video_out)     (uint16_t addr, uint8_t val);
  164.43 +extern void (*video_mono_out)(uint16_t addr, uint8_t val);
  164.44 +extern uint8_t (*video_in)     (uint16_t addr);
  164.45 +extern uint8_t (*video_mono_in)(uint16_t addr);
  164.46 +
  164.47 +extern void (*video_write_a000)(uint32_t addr, uint8_t val);
  164.48 +extern void (*video_write_b000)(uint32_t addr, uint8_t val);
  164.49 +extern void (*video_write_b800)(uint32_t addr, uint8_t val);
  164.50 +
  164.51 +extern uint8_t (*video_read_a000)(uint32_t addr);
  164.52 +extern uint8_t (*video_read_b000)(uint32_t addr);
  164.53 +extern uint8_t (*video_read_b800)(uint32_t addr);
  164.54 +
  164.55 +extern void (*video_write_a000_w)(uint32_t addr, uint16_t val);
  164.56 +extern void (*video_write_a000_l)(uint32_t addr, uint32_t val);
  164.57 +
  164.58 +extern void    video_out_null(uint16_t addr, uint8_t val);
  164.59 +extern uint8_t video_in_null(uint16_t addr);
  164.60 +
  164.61 +extern void    video_write_null(uint32_t addr, uint8_t val);
  164.62 +extern uint8_t video_read_null (uint32_t addr);
  164.63 +
  164.64 +
  164.65 +extern uint8_t tridentoldctrl2,tridentnewctrl2;
  164.66 +extern int rowdbl;
  164.67 +
  164.68 +typedef struct
  164.69 +{
  164.70 +        int w, h;
  164.71 +        uint8_t *dat;
  164.72 +        uint8_t *line[0];
  164.73 +} BITMAP;
  164.74 +
  164.75 +extern BITMAP *buffer,*buffer32,*vbuf;
  164.76 +
  164.77 +extern BITMAP *screen;
  164.78 +
  164.79 +extern int wx,wy;
  164.80 +
  164.81 +extern uint8_t fontdat[256][8];
  164.82 +extern uint8_t fontdatm[256][16];
  164.83 +
  164.84 +
  164.85 +extern int xsize,ysize;
  164.86 +
  164.87 +extern int dacread,dacwrite,dacpos;
  164.88 +
  164.89 +typedef struct
  164.90 +{
  164.91 +        uint8_t r, g, b;
  164.92 +} RGB;
  164.93 +        
  164.94 +typedef RGB PALETTE[256];
  164.95 +extern PALETTE vgapal;
  164.96 +extern int palchange;
  164.97 +
  164.98 +
  164.99 +extern uint32_t vrammask;
 164.100 +
 164.101 +typedef struct
 164.102 +{
 164.103 +        int     (*init)();
 164.104 +        void    (*out)(uint16_t addr, uint8_t val);
 164.105 +        uint8_t (*in)(uint16_t addr);
 164.106 +        void    (*mono_out)(uint16_t addr, uint8_t val);
 164.107 +        uint8_t (*mono_in)(uint16_t addr);
 164.108 +        void    (*poll)();
 164.109 +        void    (*recalctimings)();
 164.110 +        void    (*write_a000)(uint32_t addr, uint8_t val);
 164.111 +        void    (*write_b000)(uint32_t addr, uint8_t val);
 164.112 +        void    (*write_b800)(uint32_t addr, uint8_t val);
 164.113 +        uint8_t (*read_a000)(uint32_t addr);
 164.114 +        uint8_t (*read_b000)(uint32_t addr);
 164.115 +        uint8_t (*read_b800)(uint32_t addr);
 164.116 +} GFXCARD;
 164.117 +
 164.118 +extern GFXCARD vid_cga;
 164.119 +extern GFXCARD vid_mda;
 164.120 +extern GFXCARD vid_hercules;
 164.121 +extern GFXCARD vid_pc1512;
 164.122 +extern GFXCARD vid_pc1640;
 164.123 +extern GFXCARD vid_pc200;
 164.124 +extern GFXCARD vid_m24;
 164.125 +extern GFXCARD vid_paradise;
 164.126 +extern GFXCARD vid_tandy;
 164.127 +extern GFXCARD vid_ega;
 164.128 +extern GFXCARD vid_oti067;
 164.129 +extern GFXCARD vid_tvga;
 164.130 +extern GFXCARD vid_et4000;
 164.131 +extern GFXCARD vid_et4000w32p;
 164.132 +extern GFXCARD vid_s3;
 164.133 +
 164.134 +
 164.135 +extern float cpuclock;
 164.136 +
 164.137 +extern int emu_fps, frames;
 164.138 +
 164.139 +#define makecol(r, g, b)    ((b) | ((g) << 8) | ((r) << 16))
 164.140 +#define makecol32(r, g, b)  ((b) | ((g) << 8) | ((r) << 16))
 164.141 +
 164.142 +extern int readflash;
 164.143 +
 164.144 +extern void (*video_recalctimings)();
 164.145 +
 164.146 +extern void (*video_blit_memtoscreen)(int x, int y, int y1, int y2, int w, int h);
 164.147 +extern void (*video_blit_memtoscreen_8)(int x, int y, int w, int h);
 164.148 +
 164.149 +
 164.150 +extern int video_timing_b, video_timing_w, video_timing_l;
 164.151 +extern int video_speed;
 164.152 +
 164.153 +extern int video_res_x, video_res_y, video_bpp;
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/src/wd76c10.c	Sun Apr 21 14:54:35 2013 +0100
   165.3 @@ -0,0 +1,102 @@
   165.4 +#include "ibm.h"
   165.5 +#include "fdc.h"
   165.6 +#include "io.h"
   165.7 +#include "mem.h"
   165.8 +#include "serial.h"
   165.9 +#include "wd76c10.h"
  165.10 +
  165.11 +static uint16_t wd76c10_0092;
  165.12 +static uint16_t wd76c10_2072;
  165.13 +static uint16_t wd76c10_2872;
  165.14 +static uint16_t wd76c10_5872;
  165.15 +
  165.16 +uint16_t wd76c10_read(uint16_t port)
  165.17 +{
  165.18 +        switch (port)
  165.19 +        {
  165.20 +                case 0x0092:
  165.21 +                return wd76c10_0092;
  165.22 +                
  165.23 +                case 0x2072:
  165.24 +                return wd76c10_2072;
  165.25 +
  165.26 +                case 0x2872:
  165.27 +                return wd76c10_2872;
  165.28 +                
  165.29 +                case 0x5872:
  165.30 +                return wd76c10_5872;
  165.31 +        }
  165.32 +        return 0;
  165.33 +}
  165.34 +
  165.35 +void wd76c10_write(uint16_t port, uint16_t val)
  165.36 +{
  165.37 +        pclog("WD76C10 write %04X %04X\n", port, val);
  165.38 +        switch (port)
  165.39 +        {
  165.40 +                case 0x0092:
  165.41 +                wd76c10_0092 = val;
  165.42 +                        
  165.43 +                mem_a20_alt = val & 2;
  165.44 +                mem_a20_recalc();
  165.45 +                break;
  165.46 +                
  165.47 +                case 0x2072:
  165.48 +                wd76c10_2072 = val;
  165.49 +                
  165.50 +                serial1_remove();
  165.51 +                serial2_remove();
  165.52 +                
  165.53 +                switch ((val >> 5) & 7)
  165.54 +                {
  165.55 +                        case 1: serial1_init(0x3f8); break;
  165.56 +                        case 2: serial1_init(0x2f8); break;
  165.57 +                        case 3: serial1_init(0x3e8); break;
  165.58 +                        case 4: serial1_init(0x2e8); break;
  165.59 +                }
  165.60 +                switch ((val >> 1) & 7)
  165.61 +                {
  165.62 +                        case 1: serial2_init(0x3f8); break;
  165.63 +                        case 2: serial2_init(0x2f8); break;
  165.64 +                        case 3: serial2_init(0x3e8); break;
  165.65 +                        case 4: serial2_init(0x2e8); break;
  165.66 +                }
  165.67 +                break;
  165.68 +
  165.69 +                case 0x2872:
  165.70 +                wd76c10_2872 = val;
  165.71 +                
  165.72 +                fdc_remove();
  165.73 +                if (!(val & 1))
  165.74 +                   fdc_init();
  165.75 +                break;
  165.76 +                
  165.77 +                case 0x5872:
  165.78 +                wd76c10_5872 = val;
  165.79 +                break;
  165.80 +        }
  165.81 +}
  165.82 +
  165.83 +uint8_t wd76c10_readb(uint16_t port)
  165.84 +{
  165.85 +        if (port & 1)
  165.86 +           return wd76c10_read(port & ~1) >> 8;
  165.87 +        return wd76c10_read(port) & 0xff;
  165.88 +}
  165.89 +
  165.90 +void wd76c10_writeb(uint16_t port, uint8_t val)
  165.91 +{
  165.92 +        uint16_t temp = wd76c10_read(port);
  165.93 +        if (port & 1)
  165.94 +           wd76c10_write(port & ~1, (temp & 0x00ff) | (val << 8));
  165.95 +        else
  165.96 +           wd76c10_write(port     , (temp & 0xff00) | val);
  165.97 +}
  165.98 +
  165.99 +void wd76c10_init()
 165.100 +{
 165.101 +        io_sethandler(0x0092, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL);
 165.102 +        io_sethandler(0x2072, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL);
 165.103 +        io_sethandler(0x2872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL);
 165.104 +        io_sethandler(0x5872, 0x0002, wd76c10_readb, wd76c10_read, NULL, wd76c10_writeb, wd76c10_write, NULL);
 165.105 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/src/wd76c10.h	Sun Apr 21 14:54:35 2013 +0100
   166.3 @@ -0,0 +1,1 @@
   166.4 +void wd76c10_init();
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/src/win-d3d.cc	Sun Apr 21 14:54:35 2013 +0100
   167.3 @@ -0,0 +1,225 @@
   167.4 +#include <stdint.h>
   167.5 +#define BITMAP WINDOWS_BITMAP
   167.6 +#include <d3d9.h>
   167.7 +#undef BITMAP
   167.8 +#include "win-d3d.h"
   167.9 +#include "video.h"
  167.10 +
  167.11 +extern "C" void fatal(const char *format, ...);
  167.12 +extern "C" void pclog(const char *format, ...);
  167.13 +
  167.14 +void d3d_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h);
  167.15 +void d3d_blit_memtoscreen_8(int x, int y, int w, int h);
  167.16 +
  167.17 +LPDIRECT3D9             d3d        = NULL;
  167.18 +LPDIRECT3DDEVICE9       d3ddev     = NULL; 
  167.19 +LPDIRECT3DVERTEXBUFFER9 v_buffer   = NULL;
  167.20 +LPDIRECT3DTEXTURE9      d3dTexture = NULL;
  167.21 +D3DPRESENT_PARAMETERS d3dpp;
  167.22 +
  167.23 +HWND d3d_hwnd;
  167.24 +
  167.25 +struct CUSTOMVERTEX
  167.26 +{
  167.27 +     FLOAT x, y, z, rhw;    // from the D3DFVF_XYZRHW flag
  167.28 +     DWORD color;    // from the D3DFVF_DIFFUSE flag
  167.29 +     FLOAT tu, tv;
  167.30 +};
  167.31 +
  167.32 +CUSTOMVERTEX OurVertices[] =
  167.33 +{
  167.34 +     {  0.0f,   0.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f},
  167.35 +     {2048.0f, 2048.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 1.0f},
  167.36 +     {  0.0f, 2048.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 1.0f},
  167.37 +
  167.38 +     {  0.0f,   0.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f},
  167.39 +     {2048.0f,   0.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0.0f},
  167.40 +     {2048.0f, 2048.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 1.0f},
  167.41 +};
  167.42 +  
  167.43 +void d3d_init(HWND h)
  167.44 +{
  167.45 +        VOID* pVoid;    // the void pointer
  167.46 +        D3DLOCKED_RECT dr;
  167.47 +        RECT r;
  167.48 +        int x, y;
  167.49 +        uint32_t *p;
  167.50 +        
  167.51 +        d3d_hwnd = h;
  167.52 +        
  167.53 +        d3d = Direct3DCreate9(D3D_SDK_VERSION);
  167.54 +
  167.55 +        memset(&d3dpp, 0, sizeof(d3dpp));      
  167.56 +
  167.57 +    d3dpp.Flags                  = D3DPRESENTFLAG_VIDEO;
  167.58 +    d3dpp.SwapEffect             = D3DSWAPEFFECT_FLIP;
  167.59 +    d3dpp.hDeviceWindow          = h;
  167.60 +    d3dpp.BackBufferCount        = 1;
  167.61 +    d3dpp.MultiSampleType        = D3DMULTISAMPLE_NONE;
  167.62 +    d3dpp.MultiSampleQuality     = 0;
  167.63 +    d3dpp.EnableAutoDepthStencil = false;
  167.64 +    d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
  167.65 +    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;
  167.66 +    d3dpp.Windowed               = true;
  167.67 +    d3dpp.BackBufferFormat       = D3DFMT_UNKNOWN;
  167.68 +    d3dpp.BackBufferWidth        = 0;
  167.69 +    d3dpp.BackBufferHeight       = 0;
  167.70 +
  167.71 +        d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, h, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
  167.72 +        
  167.73 +        d3ddev->SetTextureStageState(0,D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
  167.74 +        d3ddev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
  167.75 +        d3ddev->SetTextureStageState(0,D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  167.76 +
  167.77 +        d3ddev->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  167.78 +        d3ddev->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  167.79 +        
  167.80 +    // create the vertex and store the pointer into v_buffer, which is created globally
  167.81 +     d3ddev->CreateVertexBuffer(6*sizeof(CUSTOMVERTEX),
  167.82 +                                0,
  167.83 +                                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
  167.84 +                                D3DPOOL_MANAGED,
  167.85 +                                &v_buffer,
  167.86 +                                NULL);
  167.87 +
  167.88 +
  167.89 +     v_buffer->Lock(0, 0, (void**)&pVoid, 0);    // lock the vertex buffer
  167.90 +     memcpy(pVoid, OurVertices, sizeof(OurVertices));    // copy the vertices to the locked buffer
  167.91 +     v_buffer->Unlock();    // unlock the vertex buffer
  167.92 +     
  167.93 +     d3ddev->CreateTexture(2048, 2048, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &d3dTexture, NULL);
  167.94 +     
  167.95 +        r.top    = r.left  = 0;
  167.96 +        r.bottom = r.right = 2047;
  167.97 +        
  167.98 +        if (FAILED(d3dTexture->LockRect(0, &dr, &r, 0)))
  167.99 +           fatal("LockRect failed\n");
 167.100 +        
 167.101 +        for (y = 0; y < 2048; y++)
 167.102 +        {
 167.103 +                p = (uint32_t *)(dr.pBits + (y * dr.Pitch));
 167.104 +                for (x = 0; x < 2048; x++)
 167.105 +                {
 167.106 +                        p[x] = x + (y << 11);
 167.107 +                }
 167.108 +        }
 167.109 +        
 167.110 +        d3dTexture->UnlockRect(0);
 167.111 +        
 167.112 +//        atexit(d3d_close);
 167.113 +        
 167.114 +        video_blit_memtoscreen = d3d_blit_memtoscreen;
 167.115 +        video_blit_memtoscreen_8 = d3d_blit_memtoscreen_8;
 167.116 +}
 167.117 +
 167.118 +void d3d_resize(int x, int y)
 167.119 +{
 167.120 +//        d3d_close();
 167.121 +//        d3d_init(d3d_hwnd);
 167.122 +        d3dpp.BackBufferWidth        = 0;
 167.123 +        d3dpp.BackBufferHeight       = 0;
 167.124 +        d3ddev->Reset(&d3dpp);
 167.125 +}
 167.126 +        
 167.127 +void d3d_close()
 167.128 +{
 167.129 +        if (d3dTexture)
 167.130 +        {
 167.131 +                d3dTexture->Release();
 167.132 +                d3dTexture = NULL;
 167.133 +        }
 167.134 +        if (v_buffer)
 167.135 +        {
 167.136 +                v_buffer->Release();
 167.137 +                v_buffer = NULL;
 167.138 +        }
 167.139 +        if (d3ddev)
 167.140 +        {
 167.141 +                d3ddev->Release();
 167.142 +                d3ddev = NULL;
 167.143 +        }
 167.144 +        if (d3d)
 167.145 +        {
 167.146 +                d3d->Release();
 167.147 +                d3d = NULL;
 167.148 +        }
 167.149 +}
 167.150 +
 167.151 +void d3d_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
 167.152 +{
 167.153 +        VOID* pVoid;
 167.154 +        float xmax, ymax;
 167.155 +        D3DLOCKED_RECT dr;
 167.156 +        RECT r;
 167.157 +        uint32_t *p, *src;
 167.158 +        int yy;
 167.159 +        
 167.160 +        xmax = (float)w / 2048.0;
 167.161 +        ymax = (float)h / 2048.0;        
 167.162 +        
 167.163 +        OurVertices[1].tu = OurVertices[4].tu = OurVertices[5].tu = xmax;
 167.164 +        OurVertices[1].tv = OurVertices[2].tv = OurVertices[5].tv = ymax;
 167.165 +
 167.166 +        GetClientRect(d3d_hwnd, &r);
 167.167 +        OurVertices[1].x = OurVertices[4].x = OurVertices[5].x = r.right  - r.left;
 167.168 +        OurVertices[1].y = OurVertices[2].y = OurVertices[5].y = r.bottom - r.top;
 167.169 +        
 167.170 +        //pclog("Window %i, %i\n", 
 167.171 +
 167.172 +     v_buffer->Lock(0, 0, (void**)&pVoid, 0);    // lock the vertex buffer
 167.173 +     memcpy(pVoid, OurVertices, sizeof(OurVertices));    // copy the vertices to the locked buffer
 167.174 +     v_buffer->Unlock();    // unlock the vertex buffer
 167.175 +    // clear the window to a deep blue
 167.176 +     //d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
 167.177 +
 167.178 +        r.top    = y1;
 167.179 +        r.left   = 0;
 167.180 +        r.bottom = y2;
 167.181 +        r.right  = 2047;
 167.182 +        
 167.183 +        if (FAILED(d3dTexture->LockRect(0, &dr, &r, 0)))
 167.184 +           fatal("LockRect failed\n");
 167.185 +        
 167.186 +        for (yy = y1; yy < y2; yy++)
 167.187 +            memcpy(dr.pBits + (yy * dr.Pitch), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4);
 167.188 +
 167.189 +        d3dTexture->UnlockRect(0);
 167.190 +
 167.191 +        
 167.192 +//        d3dpp.BackBufferWidth  = r.right - r.left;
 167.193 +//	d3dpp.BackBufferHeight = r.bottom - r.top;
 167.194 +	
 167.195 +//	d3ddev->Reset(&d3dpp);
 167.196 +		
 167.197 +     d3ddev->BeginScene();    // begins the 3D scene
 167.198 +
 167.199 +        d3ddev->SetTexture( 0, d3dTexture );
 167.200 +        // select which vertex format we are using
 167.201 +         d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
 167.202 +
 167.203 +         // select the vertex buffer to display
 167.204 +         d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
 167.205 +
 167.206 +         // copy the vertex buffer to the back buffer
 167.207 +        d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
 167.208 +        
 167.209 +        d3ddev->SetTexture( 0, NULL );
 167.210 +
 167.211 +     d3ddev->EndScene();    // ends the 3D scene
 167.212 +
 167.213 +     d3ddev->Present(NULL, NULL, d3d_hwnd, NULL);    // displays the created frame
 167.214 +}
 167.215 +
 167.216 +void d3d_blit_memtoscreen_8(int x, int y, int w, int h)
 167.217 +{
 167.218 +    // clear the window to a deep blue
 167.219 +     d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
 167.220 +
 167.221 +     d3ddev->BeginScene();    // begins the 3D scene
 167.222 +
 167.223 +     // do 3D rendering on the back buffer here
 167.224 +
 167.225 +     d3ddev->EndScene();    // ends the 3D scene
 167.226 +
 167.227 +     d3ddev->Present(NULL, NULL, NULL, NULL);    // displays the created frame
 167.228 +}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/src/win-d3d.h	Sun Apr 21 14:54:35 2013 +0100
   168.3 @@ -0,0 +1,9 @@
   168.4 +#ifdef __cplusplus
   168.5 +extern "C" {
   168.6 +#endif
   168.7 +        void d3d_init(HWND h);
   168.8 +        void d3d_close();
   168.9 +        void d3d_resize(int x, int y);
  168.10 +#ifdef __cplusplus
  168.11 +}
  168.12 +#endif
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/src/win-ddraw.cc	Sun Apr 21 14:54:35 2013 +0100
   169.3 @@ -0,0 +1,291 @@
   169.4 +#include <stdint.h>
   169.5 +#define BITMAP WINDOWS_BITMAP
   169.6 +#include <ddraw.h>
   169.7 +#undef BITMAP
   169.8 +#include "win-ddraw.h"
   169.9 +#include "video.h"
  169.10 +
  169.11 +extern "C" void fatal(const char *format, ...);
  169.12 +extern "C" void pclog(const char *format, ...);
  169.13 +
  169.14 +extern "C" void ddraw_init(HWND h);
  169.15 +extern "C" void ddraw_close();
  169.16 +extern "C" void ddraw_draw();
  169.17 +
  169.18 +LPDIRECTDRAW  lpdd  = NULL;
  169.19 +LPDIRECTDRAW4 lpdd4 = NULL;
  169.20 +LPDIRECTDRAWSURFACE4 lpdds_pri = NULL;
  169.21 +LPDIRECTDRAWSURFACE4 lpdds_back = NULL;
  169.22 +LPDIRECTDRAWSURFACE4 lpdds_back2 = NULL;
  169.23 +LPDIRECTDRAWCLIPPER lpdd_clipper = NULL;
  169.24 +DDSURFACEDESC2 ddsd;
  169.25 +
  169.26 +HWND ddraw_hwnd;
  169.27 +
  169.28 +static PALETTE cgapal=
  169.29 +{
  169.30 +        {0,0,0},{0,42,0},{42,0,0},{42,21,0},
  169.31 +        {0,0,0},{0,42,42},{42,0,42},{42,42,42},
  169.32 +        {0,0,0},{21,63,21},{63,21,21},{63,63,21},
  169.33 +        {0,0,0},{21,63,63},{63,21,63},{63,63,63},
  169.34 +
  169.35 +        {0,0,0},{0,0,42},{0,42,0},{0,42,42},
  169.36 +        {42,0,0},{42,0,42},{42,21,00},{42,42,42},
  169.37 +        {21,21,21},{21,21,63},{21,63,21},{21,63,63},
  169.38 +        {63,21,21},{63,21,63},{63,63,21},{63,63,63},
  169.39 +
  169.40 +        {0,0,0},{0,21,0},{0,0,42},{0,42,42},
  169.41 +        {42,0,21},{21,10,21},{42,0,42},{42,0,63},
  169.42 +        {21,21,21},{21,63,21},{42,21,42},{21,63,63},
  169.43 +        {63,0,0},{42,42,0},{63,21,42},{41,41,41},
  169.44 +        
  169.45 +        {0,0,0},{0,42,42},{42,0,0},{42,42,42},
  169.46 +        {0,0,0},{0,42,42},{42,0,0},{42,42,42},
  169.47 +        {0,0,0},{0,63,63},{63,0,0},{63,63,63},
  169.48 +        {0,0,0},{0,63,63},{63,0,0},{63,63,63},
  169.49 +};
  169.50 +
  169.51 +static uint32_t pal_lookup[256];
  169.52 +        
  169.53 +void ddraw_init(HWND h)
  169.54 +{
  169.55 +        int c;
  169.56 +        
  169.57 +        for (c = 0; c < 256; c++)
  169.58 +            pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2);
  169.59 +
  169.60 +        if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
  169.61 +           fatal("DirectDrawCreate failed\n");
  169.62 +        
  169.63 +        if (FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4)))
  169.64 +           fatal("QueryInterface failed\n");
  169.65 +
  169.66 +        lpdd->Release();
  169.67 +        lpdd = NULL;
  169.68 +        
  169.69 +        atexit(ddraw_close);
  169.70 +
  169.71 +        if (FAILED(lpdd4->SetCooperativeLevel(h, DDSCL_NORMAL)))
  169.72 +           fatal("SetCooperativeLevel failed\n");
  169.73 +           
  169.74 +        memset(&ddsd, 0, sizeof(ddsd));
  169.75 +        ddsd.dwSize = sizeof(ddsd);
  169.76 +        
  169.77 +        ddsd.dwFlags = DDSD_CAPS;
  169.78 +        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  169.79 +        if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL)))
  169.80 +           fatal("CreateSurface failed\n");
  169.81 +        
  169.82 +        memset(&ddsd, 0, sizeof(ddsd));
  169.83 +        ddsd.dwSize = sizeof(ddsd);
  169.84 +        
  169.85 +        ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  169.86 +        ddsd.dwWidth  = 2048;
  169.87 +        ddsd.dwHeight = 2048;
  169.88 +        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
  169.89 +        if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL)))
  169.90 +           fatal("CreateSurface back failed\n");
  169.91 +
  169.92 +        memset(&ddsd, 0, sizeof(ddsd));
  169.93 +        ddsd.dwSize = sizeof(ddsd);
  169.94 +        
  169.95 +        ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  169.96 +        ddsd.dwWidth  = 2048;
  169.97 +        ddsd.dwHeight = 2048;
  169.98 +        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
  169.99 +        if (FAILED(lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL)))
 169.100 +           fatal("CreateSurface back failed\n");
 169.101 +           
 169.102 +        if (FAILED(lpdd4->CreateClipper(0, &lpdd_clipper, NULL)))
 169.103 +           fatal("CreateClipper failed\n");
 169.104 +        if (FAILED(lpdd_clipper->SetHWnd(0, h)))
 169.105 +           fatal("SetHWnd failed\n");
 169.106 +        if (FAILED(lpdds_pri->SetClipper(lpdd_clipper)))
 169.107 +           fatal("SetClipper failed\n");
 169.108 +
 169.109 +        pclog("DDRAW_INIT complete\n");
 169.110 +        ddraw_hwnd = h;
 169.111 +        video_blit_memtoscreen   = ddraw_blit_memtoscreen;
 169.112 +        video_blit_memtoscreen_8 = ddraw_blit_memtoscreen_8;
 169.113 +}
 169.114 +
 169.115 +void ddraw_close()
 169.116 +{
 169.117 +        if (lpdds_back2)
 169.118 +        {
 169.119 +                lpdds_back2->Release();
 169.120 +                lpdds_back2 = NULL;
 169.121 +        }
 169.122 +        if (lpdds_back)
 169.123 +        {
 169.124 +                lpdds_back->Release();
 169.125 +                lpdds_back = NULL;
 169.126 +        }
 169.127 +        if (lpdds_pri)
 169.128 +        {
 169.129 +                lpdds_pri->Release();
 169.130 +                lpdds_pri = NULL;
 169.131 +        }
 169.132 +        if (lpdd_clipper)
 169.133 +        {
 169.134 +                lpdd_clipper->Release();
 169.135 +                lpdd_clipper = NULL;
 169.136 +        }
 169.137 +        if (lpdd4)
 169.138 +        {
 169.139 +                lpdd4->Release();
 169.140 +                lpdd4 = NULL;
 169.141 +        }
 169.142 +}
 169.143 +
 169.144 +void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
 169.145 +{
 169.146 +        RECT r_src;
 169.147 +        RECT r_dest;
 169.148 +        int xx, yy;
 169.149 +        POINT po;
 169.150 +        uint32_t *p;
 169.151 +        HRESULT hr;
 169.152 +        
 169.153 +//        pclog("Blit memtoscreen %i,%i %i %i %i,%i\n", x, y, y1, y2, w, h);
 169.154 +
 169.155 +        memset(&ddsd, 0, sizeof(ddsd));
 169.156 +        ddsd.dwSize = sizeof(ddsd);
 169.157 +
 169.158 +        hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.159 +        if (hr == DDERR_SURFACELOST)
 169.160 +        {
 169.161 +                lpdds_back->Restore();
 169.162 +                lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.163 +                fullchange = changeframecount;
 169.164 +        }
 169.165 +        if (!ddsd.lpSurface) return;
 169.166 +        for (yy = y1; yy < y2; yy++)
 169.167 +            memcpy(ddsd.lpSurface + (yy * ddsd.lPitch), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4);
 169.168 +        lpdds_back->Unlock(NULL);
 169.169 +
 169.170 +        po.x = po.y = 0;
 169.171 +        
 169.172 +        ClientToScreen(ddraw_hwnd, &po);
 169.173 +        GetClientRect(ddraw_hwnd, &r_dest);
 169.174 +        OffsetRect(&r_dest, po.x, po.y);        
 169.175 +
 169.176 +        r_src.left   = 0;
 169.177 +        r_src.top    = 0;       
 169.178 +        r_src.right  = w;
 169.179 +        r_src.bottom = h;
 169.180 +
 169.181 +        hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL);
 169.182 +        if (hr == DDERR_SURFACELOST)
 169.183 +        {
 169.184 +                lpdds_back2->Restore();
 169.185 +                lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL);
 169.186 +        }
 169.187 +
 169.188 +        if (readflash)
 169.189 +        {
 169.190 +                readflash = 0;
 169.191 +                hr = lpdds_back2->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.192 +                if (hr == DDERR_SURFACELOST)
 169.193 +                {
 169.194 +                        lpdds_back2->Restore();
 169.195 +                        lpdds_back2->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.196 +                        fullchange = changeframecount;
 169.197 +                }
 169.198 +                if (!ddsd.lpSurface) return;
 169.199 +                for (yy = 8; yy < 14; yy++)
 169.200 +                {
 169.201 +                        p = (uint32_t *)(ddsd.lpSurface + (yy * ddsd.lPitch));                        
 169.202 +                        for (xx = (w - 40); xx < (w - 8); xx++)
 169.203 +                            p[xx] = 0xffffffff;
 169.204 +                }
 169.205 +        }
 169.206 +        lpdds_back2->Unlock(NULL);
 169.207 +        
 169.208 +//        pclog("Blit from %i,%i %i,%i to %i,%i %i,%i\n", r_src.left, r_src.top, r_src.right, r_src.bottom, r_dest.left, r_dest.top, r_dest.right, r_dest.bottom);
 169.209 +        hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL);
 169.210 +        if (hr == DDERR_SURFACELOST)
 169.211 +        {
 169.212 +                lpdds_pri->Restore();
 169.213 +                lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL);
 169.214 +        }
 169.215 +}
 169.216 +
 169.217 +void ddraw_blit_memtoscreen_8(int x, int y, int w, int h)
 169.218 +{
 169.219 +        RECT r_src;
 169.220 +        RECT r_dest;
 169.221 +        int xx, yy;
 169.222 +        POINT po;
 169.223 +        uint32_t *p;
 169.224 +        HRESULT hr;
 169.225 +
 169.226 +        memset(&ddsd, 0, sizeof(ddsd));
 169.227 +        ddsd.dwSize = sizeof(ddsd);
 169.228 +
 169.229 +        hr = lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.230 +
 169.231 +        if (hr == DDERR_SURFACELOST)
 169.232 +        {
 169.233 +                lpdds_back->Restore();
 169.234 +                lpdds_back->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.235 +                fullchange = changeframecount;
 169.236 +        }
 169.237 +        if (!ddsd.lpSurface) return;
 169.238 +        for (yy = 0; yy < h; yy++)
 169.239 +        {
 169.240 +                if ((y + yy) >= 0 && (y + yy) < buffer->h)
 169.241 +                {
 169.242 +                        p = (uint32_t *)(ddsd.lpSurface + (yy * ddsd.lPitch));
 169.243 +                        for (xx = 0; xx < w; xx++)
 169.244 +                            p[xx] = pal_lookup[buffer->line[y + yy][x + xx]];
 169.245 +                }
 169.246 +        }
 169.247 +        p = (uint32_t *)(ddsd.lpSurface + (4 * ddsd.lPitch));
 169.248 +        lpdds_back->Unlock(NULL);
 169.249 +
 169.250 +        po.x = po.y = 0;
 169.251 +        
 169.252 +        ClientToScreen(ddraw_hwnd, &po);
 169.253 +        GetClientRect(ddraw_hwnd, &r_dest);
 169.254 +        OffsetRect(&r_dest, po.x, po.y);        
 169.255 +
 169.256 +        r_src.left   = 0;
 169.257 +        r_src.top    = 0;       
 169.258 +        r_src.right  = w;
 169.259 +        r_src.bottom = h;
 169.260 +
 169.261 +        hr = lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL);
 169.262 +        if (hr == DDERR_SURFACELOST)
 169.263 +        {
 169.264 +                lpdds_back2->Restore();
 169.265 +                lpdds_back2->Blt(&r_src, lpdds_back, &r_src, DDBLT_WAIT, NULL);
 169.266 +        }
 169.267 +
 169.268 +        if (readflash)
 169.269 +        {
 169.270 +                readflash = 0;
 169.271 +                hr = lpdds_back2->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.272 +                if (hr == DDERR_SURFACELOST)
 169.273 +                {
 169.274 +                        lpdds_back2->Restore();
 169.275 +                        lpdds_back2->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
 169.276 +                        fullchange = changeframecount;
 169.277 +                }
 169.278 +                if (!ddsd.lpSurface) return;
 169.279 +                for (yy = 8; yy < 14; yy++)
 169.280 +                {
 169.281 +                        p = (uint32_t *)(ddsd.lpSurface + (yy * ddsd.lPitch));                        
 169.282 +                        for (xx = (w - 40); xx < (w - 8); xx++)
 169.283 +                            p[xx] = 0xffffffff;
 169.284 +                }
 169.285 +                lpdds_back2->Unlock(NULL);
 169.286 +        }
 169.287 +        
 169.288 +        hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL);
 169.289 +        if (hr == DDERR_SURFACELOST)
 169.290 +        {
 169.291 +                lpdds_pri->Restore();
 169.292 +                hr = lpdds_pri->Blt(&r_dest, lpdds_back2, &r_src, DDBLT_WAIT, NULL);
 169.293 +        }
 169.294 +}
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/src/win-ddraw.h	Sun Apr 21 14:54:35 2013 +0100
   170.3 @@ -0,0 +1,12 @@
   170.4 +#ifdef __cplusplus
   170.5 +extern "C" {
   170.6 +#endif
   170.7 +        void ddraw_init(HWND h);
   170.8 +        void ddraw_close();
   170.9 +        
  170.10 +        void ddraw_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h);
  170.11 +        void ddraw_blit_memtoscreen_8(int x, int y, int w, int h);
  170.12 +#ifdef __cplusplus
  170.13 +}
  170.14 +#endif
  170.15 +
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/src/win-keyboard.cc	Sun Apr 21 14:54:35 2013 +0100
   171.3 @@ -0,0 +1,109 @@
   171.4 +#include <stdio.h>
   171.5 +#include <string.h>
   171.6 +#include <stdint.h>
   171.7 +#define DIRECTINPUT_VERSION	0x0700
   171.8 +#include <dinput.h>
   171.9 +#include "plat-keyboard.h"
  171.10 +#include "win.h"
  171.11 +
  171.12 +extern "C" int key[256];
  171.13 +uint8_t dinput_key[256];
  171.14 +
  171.15 +extern "C" void fatal(const char *format, ...);
  171.16 +extern "C" void pclog(const char *format, ...);
  171.17 +
  171.18 +extern "C" void keyboard_init();
  171.19 +extern "C" void keyboard_close();
  171.20 +extern "C" void keyboard_poll();
  171.21 +
  171.22 +LPDIRECTINPUT lpdi = NULL;
  171.23 +LPDIRECTINPUTDEVICE lpdi_key = NULL;
  171.24 +
  171.25 +static int keyboard_lookup[256] = 
  171.26 +{
  171.27 +        -1,             DIK_ESCAPE,  DIK_1,           DIK_2,         DIK_3,       DIK_4,        DIK_5,          DIK_6,        /*00*/
  171.28 +        DIK_7,          DIK_8,       DIK_9,           DIK_0,         DIK_MINUS,   DIK_EQUALS,   DIK_BACKSPACE,  DIK_TAB,      /*08*/
  171.29 +        DIK_Q,          DIK_W,       DIK_E,           DIK_R,         DIK_T,       DIK_Y,        DIK_U,          DIK_I,        /*10*/
  171.30 +        DIK_O,          DIK_P,       DIK_LBRACKET,    DIK_RBRACKET,  DIK_RETURN,  DIK_LCONTROL, DIK_A,          DIK_S,        /*18*/
  171.31 +        DIK_D,          DIK_F,       DIK_G,           DIK_H,         DIK_J,       DIK_K,        DIK_L,          DIK_SEMICOLON,/*20*/
  171.32 +        DIK_APOSTROPHE, DIK_GRAVE,   DIK_LSHIFT,      DIK_BACKSLASH, DIK_Z,       DIK_X,        DIK_C,          DIK_V,        /*28*/  
  171.33 +        DIK_B,          DIK_N,       DIK_M,           DIK_COMMA,     DIK_PERIOD,  DIK_SLASH,    DIK_RSHIFT,     DIK_MULTIPLY, /*30*/
  171.34 +        DIK_LMENU,      DIK_SPACE,   DIK_CAPSLOCK,    DIK_F1,        DIK_F2,      DIK_F3,       DIK_F4,         DIK_F5,       /*38*/
  171.35 +        DIK_F6,         DIK_F7,      DIK_F8,          DIK_F9,        DIK_F10,     DIK_NUMLOCK,  DIK_SCROLL,     DIK_NUMPAD7,  /*40*/
  171.36 +        DIK_NUMPAD8,    DIK_NUMPAD9, DIK_NUMPADMINUS, DIK_NUMPAD4,   DIK_NUMPAD5, DIK_NUMPAD6,  DIK_NUMPADPLUS, DIK_NUMPAD1,  /*48*/
  171.37 +        DIK_NUMPAD2,    DIK_NUMPAD3, DIK_NUMPAD0,     DIK_DECIMAL,   DIK_SYSRQ,   -1,           DIK_OEM_102,    DIK_F11,      /*50*/
  171.38 +        DIK_F12,        -1,          -1,              DIK_LWIN,      DIK_RWIN,    DIK_LMENU,    -1,             -1,           /*58*/
  171.39 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*60*/
  171.40 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*68*/
  171.41 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*70*/
  171.42 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*78*/
  171.43 +        
  171.44 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*80*/
  171.45 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*88*/
  171.46 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*90*/
  171.47 +        -1,             -1,          -1,              -1,        DIK_NUMPADENTER, DIK_RCONTROL, -1,             -1,           /*98*/
  171.48 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*a0*/
  171.49 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*a8*/
  171.50 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*b0*/
  171.51 +        DIK_RMENU,      -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*b8*/ 
  171.52 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             DIK_HOME,     /*c0*/
  171.53 +        DIK_UP,         DIK_PRIOR,   -1,              DIK_LEFT,      -1,          DIK_RIGHT,    -1,             DIK_END,      /*c8*/
  171.54 +        DIK_DOWN,       DIK_NEXT,    DIK_INSERT,      DIK_DELETE,    -1,          -1,           -1,             -1,           /*d0*/ 
  171.55 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*d8*/
  171.56 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*e0*/
  171.57 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*e8*/
  171.58 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             -1,           /*f0*/ 
  171.59 +        -1,             -1,          -1,              -1,            -1,          -1,           -1,             DIK_PAUSE,    /*f8*/
  171.60 +
  171.61 +};
  171.62 +        
  171.63 +void keyboard_init()
  171.64 +{
  171.65 +        atexit(keyboard_close);
  171.66 +        
  171.67 +        if (FAILED(DirectInputCreate(hinstance, DIRECTINPUT_VERSION, &lpdi, NULL)))
  171.68 +           fatal("install_keyboard : DirectInputCreate failed\n");
  171.69 +        if (FAILED(lpdi->CreateDevice(GUID_SysKeyboard, &lpdi_key, NULL)))
  171.70 +           fatal("install_keyboard : CreateDevice failed\n");
  171.71 +        if (FAILED(lpdi_key->SetCooperativeLevel(ghwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
  171.72 +           fatal("install_keyboard : SetCooperativeLevel failed\n");
  171.73 +        if (FAILED(lpdi_key->SetDataFormat(&c_dfDIKeyboard)))
  171.74 +           fatal("install_keyboard : SetDataFormat failed\n");
  171.75 +        if (FAILED(lpdi_key->Acquire()))
  171.76 +           fatal("install_keyboard : Acquire failed\n");
  171.77 +                      
  171.78 +        memset(key, 0, sizeof(key));
  171.79 +}
  171.80 +
  171.81 +void keyboard_close()
  171.82 +{
  171.83 +        if (lpdi_key)
  171.84 +        {
  171.85 +                lpdi_key->Release();
  171.86 +                lpdi_key = NULL;
  171.87 +        }
  171.88 +        if (lpdi)
  171.89 +        {
  171.90 +                lpdi->Release();
  171.91 +                lpdi = NULL;
  171.92 +        }
  171.93 +}
  171.94 +
  171.95 +void keyboard_poll_host()
  171.96 +{
  171.97 +        int c;
  171.98 +        if (FAILED(lpdi_key->GetDeviceState(256, (LPVOID)dinput_key)))
  171.99 +        {
 171.100 +                lpdi_key->Acquire();
 171.101 +                lpdi_key->GetDeviceState(256, (LPVOID)dinput_key);
 171.102 +        }
 171.103 +        for (c = 0; c < 256; c++)
 171.104 +        {
 171.105 +                if (dinput_key[c] & 0x80) pclog("Dinput key down %i %02X\n", c, c);
 171.106 +                if (keyboard_lookup[c] != -1)
 171.107 +                {
 171.108 +                        key[c] = dinput_key[keyboard_lookup[c]] & 0x80;
 171.109 +                        if (key[c]) pclog("Key down %i %02X  %i %02X\n", c, c, keyboard_lookup[c], keyboard_lookup[c]);
 171.110 +                }
 171.111 +        }
 171.112 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/src/win-mouse.cc	Sun Apr 21 14:54:35 2013 +0100
   172.3 @@ -0,0 +1,72 @@
   172.4 +#include <dinput.h>
   172.5 +#include "plat-mouse.h"
   172.6 +#include "plat-dinput.h"
   172.7 +#include "win.h"
   172.8 +
   172.9 +extern "C" void fatal(const char *format, ...);
  172.10 +extern "C" void pclog(const char *format, ...);
  172.11 +
  172.12 +extern "C" void mouse_init();
  172.13 +extern "C" void mouse_close();
  172.14 +extern "C" void poll_mouse();
  172.15 +extern "C" void position_mouse(int x, int y);
  172.16 +extern "C" void get_mouse_mickeys(int *x, int *y);
  172.17 +
  172.18 +static LPDIRECTINPUTDEVICE lpdi_mouse = NULL;
  172.19 +static DIMOUSESTATE mousestate;
  172.20 +static int mouse_x = 0, mouse_y = 0;
  172.21 +int mouse_b = 0;
  172.22 +
  172.23 +void mouse_init()
  172.24 +{
  172.25 +        atexit(mouse_close);
  172.26 +        
  172.27 +        if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &lpdi_mouse, NULL)))
  172.28 +           fatal("mouse_init : CreateDevice failed\n");
  172.29 +        if (FAILED(lpdi_mouse->SetCooperativeLevel(ghwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
  172.30 +           fatal("mouse_init : SetCooperativeLevel failed\n");
  172.31 +        if (FAILED(lpdi_mouse->SetDataFormat(&c_dfDIMouse)))
  172.32 +           fatal("mouse_init : SetDataFormat failed\n");
  172.33 +        if (FAILED(lpdi_mouse->Acquire()))
  172.34 +           fatal("mouse_init : Acquire failed\n");
  172.35 +}
  172.36 +
  172.37 +void mouse_close()
  172.38 +{
  172.39 +        if (lpdi_mouse)
  172.40 +        {
  172.41 +                lpdi_mouse->Release();
  172.42 +                lpdi_mouse = NULL;
  172.43 +        }
  172.44 +}
  172.45 +
  172.46 +void poll_mouse()
  172.47 +{
  172.48 +        if (FAILED(lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate)))
  172.49 +        {
  172.50 +                lpdi_mouse->Acquire();
  172.51 +                lpdi_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate);
  172.52 +        }                
  172.53 +        mouse_b = 0;
  172.54 +        if (mousestate.rgbButtons[0] & 0x80)
  172.55 +           mouse_b |= 1;
  172.56 +        if (mousestate.rgbButtons[1] & 0x80)
  172.57 +           mouse_b |= 2;
  172.58 +        if (mousestate.rgbButtons[2] & 0x80)
  172.59 +           mouse_b |= 4;
  172.60 +        mouse_x += mousestate.lX;
  172.61 +        mouse_y += mousestate.lY;        
  172.62 +        if (!mousecapture)
  172.63 +           mouse_x = mouse_y = mouse_b = 0;
  172.64 +}
  172.65 +
  172.66 +void position_mouse(int x, int y)
  172.67 +{
  172.68 +}
  172.69 +
  172.70 +void get_mouse_mickeys(int *x, int *y)
  172.71 +{
  172.72 +        *x = mouse_x;
  172.73 +        *y = mouse_y;
  172.74 +        mouse_x = mouse_y = 0;
  172.75 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/src/win-opengl.c	Sun Apr 21 14:54:35 2013 +0100
   173.3 @@ -0,0 +1,148 @@
   173.4 +#define BITMAP WINDOWS_BITMAP
   173.5 +#include <windows.h>
   173.6 +#undef BITMAP
   173.7 +#include <gl\gl.h>
   173.8 +#include <gl\glu.h>
   173.9 +#include "ibm.h"
  173.10 +#include "video.h"
  173.11 +#include "win-opengl.h"
  173.12 +
  173.13 +HDC		hDC=NULL;		// Private GDI Device Context
  173.14 +HGLRC		hRC=NULL;		// Permanent Rendering Context
  173.15 +HWND            opengl_hwnd;
  173.16 +
  173.17 +
  173.18 +void opengl_init(HWND h)
  173.19 +{
  173.20 +        GLuint		PixelFormat;
  173.21 +        PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be
  173.22 +	{
  173.23 +		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
  173.24 +		1,											// Version Number
  173.25 +		PFD_DRAW_TO_WINDOW |						// Format Must Support Window
  173.26 +		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
  173.27 +		PFD_DOUBLEBUFFER,							// Must Support Double Buffering
  173.28 +		PFD_TYPE_RGBA,								// Request An RGBA Format
  173.29 +		16,										// Select Our Color Depth
  173.30 +		0, 0, 0, 0, 0, 0,							// Color Bits Ignored
  173.31 +		0,											// No Alpha Buffer
  173.32 +		0,											// Shift Bit Ignored
  173.33 +		0,											// No Accumulation Buffer
  173.34 +		0, 0, 0, 0,									// Accumulation Bits Ignored
  173.35 +		16,											// 16Bit Z-Buffer (Depth Buffer)  
  173.36 +		0,											// No Stencil Buffer
  173.37 +		0,											// No Auxiliary Buffer
  173.38 +		PFD_MAIN_PLANE,								// Main Drawing Layer
  173.39 +		0,											// Reserved
  173.40 +		0, 0, 0										// Layer Masks Ignored
  173.41 +	};
  173.42 +	
  173.43 +	if (!(hDC = GetDC(h)))
  173.44 +	   fatal("Couldn't get DC\n");
  173.45 +	if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
  173.46 +	   fatal("Couldn't choose pixel format\n");
  173.47 +	if (!SetPixelFormat(hDC, PixelFormat, &pfd))   
  173.48 +	   fatal("Couldn't set pixel format\n");
  173.49 +	if (!(hRC = wglCreateContext(hDC)))
  173.50 +	   fatal("Couldn't create rendering context\n");
  173.51 +	if (!wglMakeCurrent(hDC, hRC))
  173.52 +	   fatal("Couldn't set rendering context\n");
  173.53 +	   
  173.54 +	ShowWindow(h, SW_SHOW);
  173.55 +	   
  173.56 +	glViewport(0, 0, 200, 200);						// Reset The Current Viewport
  173.57 +
  173.58 +	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
  173.59 +	glLoadIdentity();								// Reset The Projection Matrix
  173.60 +
  173.61 +	// Calculate The Aspect Ratio Of The Window
  173.62 +	gluPerspective(45.0f, (GLfloat)200/(GLfloat)200, 0.1f, 100.0f);
  173.63 +
  173.64 +	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
  173.65 +	glLoadIdentity();								// Reset The Modelview Matrix
  173.66 +
  173.67 +	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
  173.68 +	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
  173.69 +	glClearDepth(1.0f);									// Depth Buffer Setup
  173.70 +	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
  173.71 +	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
  173.72 +	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations
  173.73 +
  173.74 +                glDisable(GL_ALPHA_TEST);
  173.75 +                glDisable(GL_BLEND);
  173.76 +                glEnable(GL_DEPTH_TEST);
  173.77 +                glDisable(GL_POLYGON_SMOOTH);
  173.78 +                glDisable(GL_STENCIL_TEST);
  173.79 +                glEnable(GL_DITHER);
  173.80 +                glDisable(GL_TEXTURE_2D);
  173.81 +                glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  173.82 +                glClearColor(0.0, 0.0, 0.0, 0.0);
  173.83 +
  173.84 +        	glMatrixMode(GL_PROJECTION);
  173.85 +        	glLoadIdentity();
  173.86 +	
  173.87 +	opengl_hwnd = h;
  173.88 +	atexit(opengl_close);	
  173.89 +	pclog("opengl_init\n");
  173.90 +}
  173.91 +
  173.92 +void opengl_close()
  173.93 +{
  173.94 +        pclog("opengl_close\n");
  173.95 +        if (hRC)
  173.96 +        {
  173.97 +                wglMakeCurrent(NULL, NULL);
  173.98 +                wglDeleteContext(hRC);
  173.99 +                hRC = NULL;
 173.100 +        }
 173.101 +        if (hDC)
 173.102 +        {
 173.103 +                ReleaseDC(opengl_hwnd, hDC);
 173.104 +                hDC = NULL;
 173.105 +        }                
 173.106 +}
 173.107 +
 173.108 +void opengl_resize(int x, int y)
 173.109 +{
 173.110 +        x = y = 200;
 173.111 +	glViewport(0, 0, x, y);						// Reset The Current Viewport
 173.112 +
 173.113 +	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
 173.114 +	glLoadIdentity();								// Reset The Projection Matrix
 173.115 +
 173.116 +	// Calculate The Aspect Ratio Of The Window
 173.117 +	gluPerspective(45.0f, (GLfloat)x/(GLfloat)y, 0.1f, 100.0f);
 173.118 +
 173.119 +	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
 173.120 +	glLoadIdentity();								// Reset The Modelview Matrix
 173.121 +}
 173.122 +
 173.123 +void opengl_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
 173.124 +{
 173.125 +        pclog("blit memtoscreen\n");
 173.126 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
 173.127 +	glLoadIdentity();									// Reset The Current Modelview Matrix
 173.128 +	glColor3f(1.0f, 1.0f, 0.0f);
 173.129 +	glTranslatef(-1.5f,0.0f,-6.0f);						// Move Left 1.5 Units And Into The Screen 6.0
 173.130 +	glBegin(GL_TRIANGLES);								// Drawing Using Triangles
 173.131 +		glVertex3f( 0.0f, 1.0f, 0.0f);					// Top
 173.132 +		glVertex3f(-1.0f,-1.0f, 0.0f);					// Bottom Left
 173.133 +		glVertex3f( 1.0f,-1.0f, 0.0f);					// Bottom Right
 173.134 +	glEnd();											// Finished Drawing The Triangle
 173.135 +	glTranslatef(3.0f,0.0f,0.0f);						// Move Right 3 Units
 173.136 +	glBegin(GL_QUADS);									// Draw A Quad
 173.137 +		glVertex3f(-1.0f, 1.0f, 0.0f);					// Top Left
 173.138 +		glVertex3f( 1.0f, 1.0f, 0.0f);					// Top Right
 173.139 +		glVertex3f( 1.0f,-1.0f, 0.0f);					// Bottom Right
 173.140 +		glVertex3f(-1.0f,-1.0f, 0.0f);					// Bottom Left
 173.141 +	glEnd();											// Done Drawing The Quad
 173.142 +
 173.143 +        SwapBuffers(hDC);
 173.144 +}
 173.145 +
 173.146 +void opengl_blit_memtoscreen_8(int x, int y, int w, int h)
 173.147 +{
 173.148 +        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 173.149 +        glLoadIdentity();
 173.150 +        SwapBuffers(hDC);
 173.151 +}
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/src/win-opengl.h	Sun Apr 21 14:54:35 2013 +0100
   174.3 @@ -0,0 +1,3 @@
   174.4 +void opengl_init(HWND h);
   174.5 +void opengl_close();
   174.6 +void opengl_resize(int x, int y);
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/src/win-timer.c	Sun Apr 21 14:54:35 2013 +0100
   175.3 @@ -0,0 +1,8 @@
   175.4 +int BPS_TO_TIMER(int a)
   175.5 +{
   175.6 +        return a;
   175.7 +}
   175.8 +
   175.9 +void install_int_ex(void (*rout)(), int a)
  175.10 +{
  175.11 +}
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/src/win-video.c	Sun Apr 21 14:54:35 2013 +0100
   176.3 @@ -0,0 +1,49 @@
   176.4 +#include <stdint.h>
   176.5 +#include "video.h"
   176.6 +
   176.7 +BITMAP *screen;
   176.8 +
   176.9 +void hline(BITMAP *b, int x1, int y, int x2, uint32_t col)
  176.10 +{
  176.11 +        if (y < 0 || y >= buffer->h)
  176.12 +           return;
  176.13 +           
  176.14 +        if (b == buffer)
  176.15 +           memset(&b->line[y][x1], col, x2 - x1);
  176.16 +        else
  176.17 +           memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4);
  176.18 +}
  176.19 +
  176.20 +void blit(BITMAP *src, BITMAP *dst, int x1, int y1, int x2, int y2, int xs, int ys)
  176.21 +{
  176.22 +}
  176.23 +
  176.24 +void stretch_blit(BITMAP *src, BITMAP *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2)
  176.25 +{
  176.26 +}
  176.27 +
  176.28 +void rectfill(BITMAP *b, int x1, int y1, int x2, int y2, uint32_t col)
  176.29 +{
  176.30 +}
  176.31 +
  176.32 +void set_palette(PALETTE p)
  176.33 +{
  176.34 +}
  176.35 +
  176.36 +void destroy_bitmap(BITMAP *b)
  176.37 +{
  176.38 +}
  176.39 +
  176.40 +BITMAP *create_bitmap(int x, int y)
  176.41 +{
  176.42 +        BITMAP *b = malloc(sizeof(BITMAP) + (y * sizeof(uint8_t *)));
  176.43 +        int c;
  176.44 +        b->dat = malloc(x * y * 4);
  176.45 +        for (c = 0; c < y; c++)
  176.46 +        {
  176.47 +                b->line[c] = b->dat + (c * x * 4);
  176.48 +        }
  176.49 +        b->w = x;
  176.50 +        b->h = y;
  176.51 +        return b;
  176.52 +}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/src/win.c	Sun Apr 21 14:54:35 2013 +0100
   177.3 @@ -0,0 +1,1644 @@
   177.4 +#define BITMAP WINDOWS_BITMAP
   177.5 +#include <windows.h>
   177.6 +#include <windowsx.h>
   177.7 +#undef BITMAP
   177.8 +
   177.9 +#include <commdlg.h>
  177.10 +
  177.11 +#include <process.h>
  177.12 +
  177.13 +#include <string.h>
  177.14 +#include <stdio.h>
  177.15 +#include <stdarg.h>
  177.16 +#include <stdlib.h>
  177.17 +#include "ibm.h"
  177.18 +#include "video.h"
  177.19 +#include "resources.h"
  177.20 +#include "ide.h"
  177.21 +
  177.22 +#include "plat-keyboard.h"
  177.23 +
  177.24 +#include "win-ddraw.h"
  177.25 +//#include "win-d3d.h"
  177.26 +//#include "win-opengl.h"
  177.27 +
  177.28 +#define TIMER_1SEC 1
  177.29 +
  177.30 +int winsizex=640,winsizey=480;
  177.31 +int svgapresent, et4000w32_present, bahamas64_present, n9_9fx_present;
  177.32 +int wakeups,wokeups;
  177.33 +#undef cs
  177.34 +CRITICAL_SECTION cs;
  177.35 +void waitmain();
  177.36 +void vsyncint();
  177.37 +int vgapresent;
  177.38 +
  177.39 +int cursoron = 1;
  177.40 +
  177.41 +HANDLE soundthreadh;
  177.42 +HANDLE blitthreadh;
  177.43 +HANDLE mainthreadh;
  177.44 +
  177.45 +void soundthread(LPVOID param);
  177.46 +void endmainthread();
  177.47 +void endsoundthread();
  177.48 +void silencesound();
  177.49 +void restoresound();
  177.50 +static HANDLE soundobject;
  177.51 +
  177.52 +static HANDLE frameobject;
  177.53 +
  177.54 +int infocus=1;
  177.55 +
  177.56 +int drawits=0;
  177.57 +void vsyncint()
  177.58 +{
  177.59 +//        if (infocus)
  177.60 +//        {
  177.61 +                        drawits++;
  177.62 +                        wakeups++;
  177.63 +                        SetEvent(frameobject);
  177.64 +//        }
  177.65 +}
  177.66 +
  177.67 +int romspresent[25];
  177.68 +int quited=0;
  177.69 +
  177.70 +RECT oldclip,pcclip;
  177.71 +int mousecapture=0;
  177.72 +int drawit;
  177.73 +/*  Declare Windows procedure  */
  177.74 +LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
  177.75 +
  177.76 +/*  Make the class name into a global variable  */
  177.77 +char szClassName[ ] = "WindowsApp";
  177.78 +
  177.79 +HWND ghwnd;
  177.80 +void updatewindowsize(int x, int y)
  177.81 +{
  177.82 +        RECT r;
  177.83 +        if (vid_resize) return;
  177.84 +        winsizex=x; winsizey=y;
  177.85 +        GetWindowRect(ghwnd,&r);
  177.86 +        MoveWindow(ghwnd,r.left,r.top,
  177.87 +                     x+(GetSystemMetrics(SM_CXFIXEDFRAME)*2),
  177.88 +                     y+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1,
  177.89 +                     TRUE);
  177.90 +//        startblit();
  177.91 +//        d3d_resize(x, y);
  177.92 +//        endblit();
  177.93 +}
  177.94 +
  177.95 +void releasemouse()
  177.96 +{
  177.97 +        if (mousecapture) 
  177.98 +        {
  177.99 +                ClipCursor(&oldclip);
 177.100 +                ShowCursor(TRUE);
 177.101 +                mousecapture = 0;
 177.102 +        }
 177.103 +}
 177.104 +
 177.105 +static LARGE_INTEGER counter_base;
 177.106 +static LARGE_INTEGER counter_freq;
 177.107 +static LARGE_INTEGER counter_pos;
 177.108 +static LARGE_INTEGER counter_posold;
 177.109 +
 177.110 +void setrefresh(int rate)
 177.111 +{
 177.112 +        return;
 177.113 +        remove_int(vsyncint);
 177.114 +        drawit=0;
 177.115 +        install_int_ex(vsyncint,BPS_TO_TIMER(rate));
 177.116 +/*        printf("Vsyncint at %i hz\n",rate);
 177.117 +        counter_freq.QuadPart=counter_base.QuadPart/rate;*/
 177.118 +//        DeleteTimerQueueTimer( &hTimer, hTimerQueue, NULL);
 177.119 +//        CreateTimerQueueTimer( &hTimer, hTimerQueue,
 177.120 +//            mainroutine, NULL , 100, 1000/rate, 0);
 177.121 +}
 177.122 +
 177.123 +void startblit()
 177.124 +{
 177.125 +        EnterCriticalSection(&cs);
 177.126 +}
 177.127 +
 177.128 +void endblit()
 177.129 +{
 177.130 +        LeaveCriticalSection(&cs);
 177.131 +}
 177.132 +
 177.133 +int mainthreadon=0;
 177.134 +
 177.135 +/*static HANDLE blitobject;
 177.136 +void blitthread(LPVOID param)
 177.137 +{
 177.138 +        while (!quited)
 177.139 +        {
 177.140 +                WaitForSingleObject(blitobject,100);
 177.141 +                if (quited) break;
 177.142 +                doblit();
 177.143 +        }
 177.144 +}
 177.145 +
 177.146 +void wakeupblit()
 177.147 +{
 177.148 +        SetEvent(blitobject);
 177.149 +}*/
 177.150 +
 177.151 +HWND statushwnd;
 177.152 +int statusopen=0;
 177.153 +extern int updatestatus;
 177.154 +extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost;
 177.155 +
 177.156 +int pause=0;
 177.157 +
 177.158 +void mainthread(LPVOID param)
 177.159 +{
 177.160 +        int t = 0;
 177.161 +        DWORD old_time, new_time;
 177.162 +        mainthreadon=1;
 177.163 +//        Sleep(500);
 177.164 +        drawits=0;
 177.165 +        old_time = GetTickCount();
 177.166 +        while (!quited)
 177.167 +        {
 177.168 +//                if (infocus)
 177.169 +//                {
 177.170 +/*                        if (!drawits)
 177.171 +                        {
 177.172 +                                while (!drawits)
 177.173 +                                {
 177.174 +                                        ResetEvent(frameobject);
 177.175 +                                        WaitForSingleObject(frameobject,10);
 177.176 +                                }
 177.177 +                        }*/
 177.178 +                        if (updatestatus)
 177.179 +                        {
 177.180 +                                updatestatus=0;
 177.181 +                                if (statusopen) SendMessage(statushwnd,WM_USER,0,0);
 177.182 +                        }
 177.183 +                        new_time = GetTickCount();
 177.184 +                        drawits += new_time - old_time;
 177.185 +                        old_time = new_time;
 177.186 +                        if (drawits > 0 && !pause)
 177.187 +                        {
 177.188 +//                                printf("Drawits %i\n",drawits);
 177.189 +                                drawits-=10;
 177.190 +                                if (drawits>50) drawits=0;
 177.191 +                                wokeups++;
 177.192 +                                startblit();
 177.193 +                                runpc();
 177.194 +//                                ddraw_draw();
 177.195 +                                endblit();
 177.196 +//#if 0                                
 177.197 +//#endif
 177.198 +                        }
 177.199 +                        else
 177.200 +                        {
 177.201 +//                                Sleep(1);
 177.202 +                        }
 177.203 +//                }
 177.204 +        }
 177.205 +        mainthreadon=0;
 177.206 +}
 177.207 +
 177.208 +HMENU menu;
 177.209 +
 177.210 +static void initmenu(void)
 177.211 +{
 177.212 +        int c;
 177.213 +        HMENU m;
 177.214 +        char s[32];
 177.215 +        m=GetSubMenu(menu,2); /*Settings*/
 177.216 +        m=GetSubMenu(m,1); /*CD-ROM*/
 177.217 +
 177.218 +        /* Loop through each Windows drive letter and test to see if
 177.219 +           it's a CDROM */
 177.220 +        for (c='A';c<='Z';c++)
 177.221 +        {
 177.222 +                sprintf(s,"%c:\\",c);
 177.223 +                if (GetDriveType(s)==DRIVE_CDROM)
 177.224 +                {
 177.225 +                        sprintf(s, "Host CD/DVD Drive (%c:)", c);
 177.226 +                        AppendMenu(m,MF_STRING,IDM_CDROM_REAL+c,s);
 177.227 +                }
 177.228 +        }
 177.229 +}
 177.230 +
 177.231 +HINSTANCE hinstance;
 177.232 +
 177.233 +void get_executable_name(char *s, int size)
 177.234 +{
 177.235 +        GetModuleFileName(hinstance, s, size);
 177.236 +}
 177.237 +
 177.238 +void set_window_title(char *s)
 177.239 +{
 177.240 +        SetWindowText(ghwnd, s);
 177.241 +}
 177.242 +
 177.243 +int WINAPI WinMain (HINSTANCE hThisInstance,
 177.244 +                    HINSTANCE hPrevInstance,
 177.245 +                    LPSTR lpszArgument,
 177.246 +                    int nFunsterStil)
 177.247 +
 177.248 +{
 177.249 +    HWND hwnd;               /* This is the handle for our window */
 177.250 +    MSG messages;            /* Here messages to the application are saved */
 177.251 +    WNDCLASSEX wincl;        /* Data structure for the windowclass */
 177.252 +    int c,d;
 177.253 +    FILE *f;
 177.254 +    int oldinfocus=0;
 177.255 +
 177.256 +        hinstance=hThisInstance;
 177.257 +    /* The Window structure */
 177.258 +    wincl.hInstance = hThisInstance;
 177.259 +    wincl.lpszClassName = szClassName;
 177.260 +    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
 177.261 +    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
 177.262 +    wincl.cbSize = sizeof (WNDCLASSEX);
 177.263 +
 177.264 +    /* Use default icon and mouse-pointer */
 177.265 +    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 177.266 +    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
 177.267 +    wincl.hCursor = NULL;//LoadCursor (NULL, IDC_ARROW);
 177.268 +    wincl.lpszMenuName = NULL;                 /* No menu */
 177.269 +    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
 177.270 +    wincl.cbWndExtra = 0;                      /* structure or the window instance */
 177.271 +    /* Use Windows's default color as the background of the window */
 177.272 +    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
 177.273 +
 177.274 +    /* Register the window class, and if it fails quit the program */
 177.275 +    if (!RegisterClassEx (&wincl))
 177.276 +        return 0;
 177.277 +
 177.278 +        menu=LoadMenu(hThisInstance,TEXT("MainMenu"));
 177.279 +        initmenu();
 177.280 +        
 177.281 +    /* The class is registered, let's create the program*/
 177.282 +    hwnd = CreateWindowEx (
 177.283 +           0,                   /* Extended possibilites for variation */
 177.284 +           szClassName,         /* Classname */
 177.285 +           "PCem v0.7",         /* Title Text */
 177.286 +           WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */
 177.287 +           CW_USEDEFAULT,       /* Windows decides the position */
 177.288 +           CW_USEDEFAULT,       /* where the window ends up on the screen */
 177.289 +           640+(GetSystemMetrics(SM_CXFIXEDFRAME)*2),                 /* The programs width */
 177.290 +           480+(GetSystemMetrics(SM_CYFIXEDFRAME)*2)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+1,                 /* and height in pixels */
 177.291 +           HWND_DESKTOP,        /* The window is a child-window to desktop */
 177.292 +           menu,                /* Menu */
 177.293 +           hThisInstance,       /* Program Instance handler */
 177.294 +           NULL                 /* No Window Creation data */
 177.295 +           );
 177.296 +
 177.297 +        /* Make the window visible on the screen */
 177.298 +        ShowWindow (hwnd, nFunsterStil);
 177.299 +
 177.300 +//        win_set_window(hwnd);
 177.301 +        
 177.302 +        ghwnd=hwnd;
 177.303 +        
 177.304 +        ddraw_init(hwnd);
 177.305 +//        d3d_init(hwnd);
 177.306 +//        opengl_init(hwnd);
 177.307 +        
 177.308 +        initpc();
 177.309 +
 177.310 +        if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE);
 177.311 +        else            SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE);
 177.312 +
 177.313 +        if (!cdrom_enabled)
 177.314 +           CheckMenuItem(menu, IDM_CDROM_DISABLED, MF_CHECKED);
 177.315 +        else           
 177.316 +           CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
 177.317 +        CheckMenuItem(menu, IDM_KEY_ALLEGRO + kb_win, MF_CHECKED);
 177.318 +        if (vid_resize) CheckMenuItem(menu, IDM_VID_RESIZE, MF_CHECKED);
 177.319 +        
 177.320 +//        set_display_switch_mode(SWITCH_BACKGROUND);
 177.321 +        
 177.322 +        d=romset;
 177.323 +        for (c=0;c<25;c++)
 177.324 +        {
 177.325 +                romset=c;
 177.326 +                romspresent[c]=loadbios();
 177.327 +                pclog("romset %i - %i\n", c, romspresent[c]);
 177.328 +        }
 177.329 +        
 177.330 +        for (c = 0; c < 25; c++)
 177.331 +        {
 177.332 +                if (romspresent[c])
 177.333 +                   break;
 177.334 +        }
 177.335 +        if (c == 25)
 177.336 +        {
 177.337 +                MessageBox(hwnd,"No ROMs present!\nYou must have at least one romset to use PCem.","PCem fatal error",MB_OK);
 177.338 +                return 0;
 177.339 +        }
 177.340 +
 177.341 +        romset=d;
 177.342 +        c=loadbios();
 177.343 +
 177.344 +        if (!c)
 177.345 +        {
 177.346 +                if (romset!=-1) MessageBox(hwnd,"Configured romset not available.\nDefaulting to available romset.","PCemu error",MB_OK);
 177.347 +                for (c=0;c<25;c++)
 177.348 +                {
 177.349 +                        if (romspresent[c])
 177.350 +                        {
 177.351 +                                romset=c;
 177.352 +                                loadbios();
 177.353 +                                break;
 177.354 +                        }
 177.355 +                }
 177.356 +        }
 177.357 +        
 177.358 +        f=romfopen("roms/trident.bin","rb");
 177.359 +        if (f)
 177.360 +        {
 177.361 +                fclose(f);
 177.362 +                vgapresent=1;
 177.363 +        }
 177.364 +        else
 177.365 +        {
 177.366 +                vgapresent=0;
 177.367 +                if (gfxcard==GFX_TVGA) gfxcard=GFX_CGA;
 177.368 +        }
 177.369 +        f=romfopen("roms/et4000.bin","rb");
 177.370 +        if (f)
 177.371 +        {
 177.372 +                fclose(f);
 177.373 +                svgapresent=1;
 177.374 +        }
 177.375 +        else
 177.376 +        {
 177.377 +                svgapresent=0;
 177.378 +                if (gfxcard==GFX_ET4000) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
 177.379 +        }
 177.380 +        f=romfopen("roms/et4000w32.bin","rb");
 177.381 +        if (f)
 177.382 +        {
 177.383 +                fclose(f);
 177.384 +                et4000w32_present=1;
 177.385 +        }
 177.386 +        else
 177.387 +        {
 177.388 +                et4000w32_present=0;
 177.389 +                if (gfxcard==GFX_ET4000W32) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
 177.390 +        }
 177.391 +        f=romfopen("roms/bahamas64.bin","rb");
 177.392 +        if (f)
 177.393 +        {
 177.394 +                fclose(f);
 177.395 +                bahamas64_present=1;
 177.396 +        }
 177.397 +        else
 177.398 +        {
 177.399 +                bahamas64_present=0;
 177.400 +                if (gfxcard==GFX_BAHAMAS64) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
 177.401 +        }
 177.402 +        f=romfopen("roms/s3_764.bin","rb");
 177.403 +        if (f)
 177.404 +        {
 177.405 +                fclose(f);
 177.406 +                n9_9fx_present=1;
 177.407 +        }
 177.408 +        else
 177.409 +        {
 177.410 +                n9_9fx_present=0;
 177.411 +                if (gfxcard==GFX_N9_9FX) gfxcard=(svgapresent)?GFX_TVGA:GFX_CGA;
 177.412 +        }
 177.413 +        timeBeginPeriod(1);
 177.414 +//        soundobject=CreateEvent(NULL, FALSE, FALSE, NULL);
 177.415 +//        soundthreadh=CreateThread(NULL,0,soundthread,NULL,NULL,NULL);
 177.416 +
 177.417 +        
 177.418 +        atexit(releasemouse);
 177.419 +//        atexit(endsoundthread);
 177.420 +        drawit=0;
 177.421 +//        QueryPerformanceFrequency(&counter_base);
 177.422 +///        QueryPerformanceCounter(&counter_posold);
 177.423 +//        counter_posold.QuadPart*=100;
 177.424 +
 177.425 +InitializeCriticalSection(&cs);
 177.426 +        frameobject=CreateEvent(NULL, FALSE, FALSE, NULL);
 177.427 +        mainthreadh=(HANDLE)_beginthread(mainthread,0,NULL);
 177.428 +//        atexit(endmainthread);
 177.429 +//        soundthreadh=(HANDLE)_beginthread(soundthread,0,NULL);
 177.430 +//        atexit(endsoundthread);
 177.431 +        SetThreadPriority(mainthreadh, THREAD_PRIORITY_HIGHEST);
 177.432 +        
 177.433 +//        blitobject=CreateEvent(NULL, FALSE, FALSE, NULL);
 177.434 +//        blitthreadh=(HANDLE)_beginthread(blitthread,0,NULL);
 177.435 +        
 177.436 +//        SetThreadPriority(soundthreadh, THREAD_PRIORITY_HIGHEST);
 177.437 +
 177.438 +        drawit=0;
 177.439 +        install_int_ex(vsyncint,BPS_TO_TIMER(100));
 177.440 +        
 177.441 +        updatewindowsize(640, 480);
 177.442 +//        focus=1;
 177.443 +//        setrefresh(100);
 177.444 +
 177.445 +//        ShowCursor(TRUE);
 177.446 +        
 177.447 +        /* Run the message loop. It will run until GetMessage() returns 0 */
 177.448 +        while (!quited)
 177.449 +        {
 177.450 +/*                if (infocus)
 177.451 +                {
 177.452 +                        if (drawits)
 177.453 +                        {
 177.454 +                                drawits--;
 177.455 +                                if (drawits>10) drawits=0;
 177.456 +                                runpc();
 177.457 +                        }
 177.458 +//;                        else
 177.459 +//                           sleep(0);
 177.460 +                        if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture)
 177.461 +                        {
 177.462 +                                ClipCursor(&oldclip);
 177.463 +                                mousecapture=0;
 177.464 +                        }
 177.465 +                }*/
 177.466 +
 177.467 +                while (GetMessage(&messages,NULL,0,0) && !quited)
 177.468 +                {
 177.469 +                        if (messages.message==WM_QUIT) quited=1;
 177.470 +                        TranslateMessage(&messages);
 177.471 +                        DispatchMessage(&messages);                        
 177.472 +                                if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END] && mousecapture)
 177.473 +                                {
 177.474 +                                        ClipCursor(&oldclip);
 177.475 +                                        ShowCursor(TRUE);
 177.476 +                                        mousecapture=0;
 177.477 +                                }
 177.478 +                }
 177.479 +
 177.480 +                quited=1;
 177.481 +//                else
 177.482 +//                sleep(10);
 177.483 +        }
 177.484 +        
 177.485 +        startblit();
 177.486 +//        pclog("Sleep 1000\n");
 177.487 +        Sleep(200);
 177.488 +//        pclog("TerminateThread\n");
 177.489 +        TerminateThread(blitthreadh,0);
 177.490 +        TerminateThread(mainthreadh,0);
 177.491 +//        pclog("Quited? %i\n",quited);
 177.492 +//        pclog("Closepc\n");
 177.493 +        closepc();
 177.494 +//        pclog("dumpregs\n");
 177.495 +        timeEndPeriod(1);
 177.496 +//        endsoundthread();
 177.497 +//        dumpregs();
 177.498 +        if (mousecapture) 
 177.499 +        {
 177.500 +                ClipCursor(&oldclip);
 177.501 +                ShowCursor(TRUE);
 177.502 +        }
 177.503 +//        pclog("Ending! %i %i\n",messages.wParam,quited);
 177.504 +        return messages.wParam;
 177.505 +}
 177.506 +
 177.507 +char openfilestring[260];
 177.508 +int getfile(HWND hwnd, char *f, char *fn)
 177.509 +{
 177.510 +        OPENFILENAME ofn;       // common dialog box structure
 177.511 +        char szFile[260];       // buffer for file name
 177.512 +        BOOL r;
 177.513 +        DWORD err;
 177.514 +
 177.515 +        // Initialize OPENFILENAME
 177.516 +        ZeroMemory(&ofn, sizeof(ofn));
 177.517 +        ofn.lStructSize = sizeof(ofn);
 177.518 +        ofn.hwndOwner = hwnd;
 177.519 +        ofn.lpstrFile = openfilestring;
 177.520 +        //
 177.521 +        // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
 177.522 +        // use the contents of szFile to initialize itself.
 177.523 +        //
 177.524 +//        ofn.lpstrFile[0] = '\0';
 177.525 +        strcpy(ofn.lpstrFile,fn);
 177.526 +        ofn.nMaxFile = sizeof(openfilestring);
 177.527 +        ofn.lpstrFilter = f;//"All\0*.*\0Text\0*.TXT\0";
 177.528 +        ofn.nFilterIndex = 1;
 177.529 +        ofn.lpstrFileTitle = NULL;
 177.530 +        ofn.nMaxFileTitle = 0;
 177.531 +        ofn.lpstrInitialDir = NULL;
 177.532 +        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 177.533 +
 177.534 +        // Display the Open dialog box.
 177.535 +
 177.536 +        pclog("GetOpenFileName - lpstrFile = %s\n", ofn.lpstrFile);
 177.537 +        r = GetOpenFileName(&ofn);
 177.538 +        if (r)
 177.539 +        {
 177.540 +                pclog("GetOpenFileName return true\n");
 177.541 +                return 0;
 177.542 +        }
 177.543 +        pclog("GetOpenFileName return false\n");
 177.544 +        err = CommDlgExtendedError();
 177.545 +        pclog("CommDlgExtendedError return %04X\n", err);
 177.546 +        return 1;
 177.547 +}
 177.548 +
 177.549 +int getsfile(HWND hwnd, char *f, char *fn)
 177.550 +{
 177.551 +        OPENFILENAME ofn;       // common dialog box structure
 177.552 +        char szFile[260];       // buffer for file name
 177.553 +        BOOL r;
 177.554 +        DWORD err;
 177.555 +
 177.556 +        // Initialize OPENFILENAME
 177.557 +        ZeroMemory(&ofn, sizeof(ofn));
 177.558 +        ofn.lStructSize = sizeof(ofn);
 177.559 +        ofn.hwndOwner = hwnd;
 177.560 +        ofn.lpstrFile = openfilestring;
 177.561 +        //
 177.562 +        // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
 177.563 +        // use the contents of szFile to initialize itself.
 177.564 +        //
 177.565 +//        ofn.lpstrFile[0] = '\0';
 177.566 +        strcpy(ofn.lpstrFile,fn);
 177.567 +        ofn.nMaxFile = sizeof(openfilestring);
 177.568 +        ofn.lpstrFilter = f;//"All\0*.*\0Text\0*.TXT\0";
 177.569 +        ofn.nFilterIndex = 1;
 177.570 +        ofn.lpstrFileTitle = NULL;
 177.571 +        ofn.nMaxFileTitle = 0;
 177.572 +        ofn.lpstrInitialDir = NULL;
 177.573 +        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 177.574 +
 177.575 +        // Display the Open dialog box.
 177.576 +
 177.577 +        pclog("GetSaveFileName - lpstrFile = %s\n", ofn.lpstrFile);
 177.578 +        r = GetSaveFileName(&ofn);
 177.579 +        if (r)
 177.580 +        {
 177.581 +                pclog("GetSaveFileName return true\n");
 177.582 +                return 0;
 177.583 +        }
 177.584 +        pclog("GetSaveFileName return false\n");
 177.585 +        err = CommDlgExtendedError();
 177.586 +        pclog("CommDlgExtendedError return %04X\n", err);
 177.587 +        return 1;
 177.588 +}
 177.589 +
 177.590 +extern int is486;
 177.591 +int romstolist[25], listtomodel[23], romstomodel[25], modeltolist[23];
 177.592 +int vidtolist[10],listtovid[10];
 177.593 +
 177.594 +int mem_list_to_size[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,32,48,64};
 177.595 +int mem_size_to_list[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,
 177.596 +                        16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,18};
 177.597 +
 177.598 +#include "cpu.h"
 177.599 +#include "model.h"
 177.600 +
 177.601 +BOOL CALLBACK configdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
 177.602 +{
 177.603 +        HWND h;
 177.604 +        int c, d;
 177.605 +        int rom,gfx,mem,fpu;
 177.606 +        int temp_cpu, temp_cpu_m, temp_model;
 177.607 +//        pclog("Dialog msg %i %08X\n",message,message);
 177.608 +        switch (message)
 177.609 +        {
 177.610 +                case WM_INITDIALOG:
 177.611 +                        pause=1;
 177.612 +                h=GetDlgItem(hdlg,IDC_COMBO1);
 177.613 +                for (c=0;c<25;c++) romstolist[c]=0;
 177.614 +                c = d = 0;
 177.615 +                while (models[c].id != -1)
 177.616 +                {
 177.617 +                        pclog("INITDIALOG : %i %i %i\n",c,models[c].id,romspresent[models[c].id]);
 177.618 +                        if (romspresent[models[c].id])
 177.619 +                        {
 177.620 +                                SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)models[c].name);
 177.621 +                                modeltolist[c] = d;
 177.622 +                                listtomodel[d] = c;
 177.623 +                                romstolist[models[c].id] = d;
 177.624 +                                romstomodel[models[c].id] = c;
 177.625 +                                d++;
 177.626 +                        }
 177.627 +                        c++;
 177.628 +                }
 177.629 +                SendMessage(h, CB_SETCURSEL, modeltolist[model], 0);
 177.630 +                
 177.631 +                h=GetDlgItem(hdlg,IDC_COMBO2);
 177.632 +                for (c=0;c<6;c++) vidtolist[c]=0;
 177.633 +                c=4;
 177.634 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"CGA"); vidtolist[GFX_CGA]=0; listtovid[0]=0;
 177.635 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"MDA"); vidtolist[GFX_MDA]=1; listtovid[1]=1;
 177.636 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Hercules"); vidtolist[GFX_HERCULES]=2; listtovid[2]=2;
 177.637 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"EGA"); vidtolist[GFX_EGA]=3; listtovid[3]=3;
 177.638 +                if (vgapresent)                 { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Trident 8900D");           vidtolist[GFX_TVGA]=c;          listtovid[c]=GFX_TVGA;          c++;       }
 177.639 +                if (svgapresent)                { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Tseng ET4000AX");          vidtolist[GFX_ET4000]=c;        listtovid[c]=GFX_ET4000;        c++;       }
 177.640 +                if (et4000w32_present)          { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Diamond Stealth 32");      vidtolist[GFX_ET4000W32]=c;     listtovid[c]=GFX_ET4000W32;     c++;       }
 177.641 +                if (bahamas64_present)          { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Paradise Bahamas 64");     vidtolist[GFX_BAHAMAS64]=c;     listtovid[c]=GFX_BAHAMAS64;     c++;       }
 177.642 +                if (n9_9fx_present)             { SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Number Nine 9FX");         vidtolist[GFX_N9_9FX]=c;        listtovid[c]=GFX_N9_9FX;        c++;       }
 177.643 +                SendMessage(h,CB_SETCURSEL,vidtolist[gfxcard],0);
 177.644 +                if (models[model].fixed_gfxcard) EnableWindow(h,FALSE);
 177.645 +
 177.646 +                h=GetDlgItem(hdlg,IDC_COMBOCPUM);
 177.647 +                c = 0;
 177.648 +                while (models[romstomodel[romset]].cpu[c].cpus != NULL && c < 3)
 177.649 +                {
 177.650 +                        SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)models[romstomodel[romset]].cpu[c].name);
 177.651 +                        c++;
 177.652 +                }
 177.653 +                EnableWindow(h,TRUE);
 177.654 +                SendMessage(h, CB_SETCURSEL, cpu_manufacturer, 0);
 177.655 +                if (c == 1) EnableWindow(h, FALSE);
 177.656 +                else        EnableWindow(h, TRUE);
 177.657 +
 177.658 +                h=GetDlgItem(hdlg,IDC_COMBO3);
 177.659 +                c = 0;
 177.660 +                while (models[romstomodel[romset]].cpu[cpu_manufacturer].cpus[c].cpu_type != -1)
 177.661 +                {
 177.662 +                        SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)models[romstomodel[romset]].cpu[cpu_manufacturer].cpus[c].name);
 177.663 +                        c++;
 177.664 +                }
 177.665 +                EnableWindow(h,TRUE);
 177.666 +                SendMessage(h, CB_SETCURSEL, cpu, 0);
 177.667 +
 177.668 +                h=GetDlgItem(hdlg,IDC_COMBOSND);
 177.669 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"None");
 177.670 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"AdLib");
 177.671 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.0");
 177.672 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v1.5");
 177.673 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster v2.0");
 177.674 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v1");
 177.675 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SB Pro v2");
 177.676 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"SoundBlaster 16");
 177.677 +                SendMessage(h,CB_SETCURSEL,sbtype,0);
 177.678 +
 177.679 +//                h=GetDlgItem(hdlg,IDC_CHECK2);
 177.680 +//                SendMessage(h,BM_SETCHECK,ADLIB,0);
 177.681 +                
 177.682 +                h=GetDlgItem(hdlg,IDC_CHECK3);
 177.683 +                SendMessage(h,BM_SETCHECK,GAMEBLASTER,0);
 177.684 +                
 177.685 +                h=GetDlgItem(hdlg,IDC_CHECK1);
 177.686 +                SendMessage(h,BM_SETCHECK,FASTDISC,0);
 177.687 +
 177.688 +                h=GetDlgItem(hdlg,IDC_CHECK2);
 177.689 +                SendMessage(h,BM_SETCHECK,slowega,0);
 177.690 +
 177.691 +                h=GetDlgItem(hdlg,IDC_CHECK4);
 177.692 +                SendMessage(h,BM_SETCHECK,cga_comp,0);
 177.693 +
 177.694 +                h=GetDlgItem(hdlg,IDC_COMBOCHC);
 177.695 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A little");
 177.696 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A bit");
 177.697 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Some");
 177.698 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"A lot");
 177.699 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Infinite");
 177.700 +                SendMessage(h,CB_SETCURSEL,cache,0);
 177.701 +
 177.702 +                h=GetDlgItem(hdlg,IDC_COMBOSPD);
 177.703 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"8-bit");
 177.704 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Slow 16-bit");
 177.705 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Fast 16-bit");
 177.706 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Slow VLB/PCI");
 177.707 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Mid  VLB/PCI");
 177.708 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"Fast VLB/PCI");                
 177.709 +                SendMessage(h,CB_SETCURSEL,video_speed,0);
 177.710 +
 177.711 +                h=GetDlgItem(hdlg,IDC_COMBOMEM);
 177.712 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"1 MB");
 177.713 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"2 MB");
 177.714 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"3 MB");
 177.715 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"4 MB");
 177.716 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"5 MB");
 177.717 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"6 MB");
 177.718 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"7 MB");
 177.719 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"8 MB");
 177.720 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"9 MB");
 177.721 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"10 MB");
 177.722 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"11 MB");
 177.723 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"12 MB");
 177.724 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"13 MB");
 177.725 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"14 MB");
 177.726 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"15 MB");
 177.727 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"16 MB");
 177.728 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"32 MB");
 177.729 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"48 MB");
 177.730 +                SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)"64 MB");
 177.731 +                SendMessage(h,CB_SETCURSEL,mem_size_to_list[mem_size-1],0);
 177.732 +                
 177.733 +                pclog("Init cpuspeed %i\n",cpuspeed);
 177.734 +
 177.735 +                return TRUE;
 177.736 +                case WM_COMMAND:
 177.737 +                switch (LOWORD(wParam))
 177.738 +                {
 177.739 +                        case IDOK:
 177.740 +                        h=GetDlgItem(hdlg,IDC_COMBO1);
 177.741 +                        temp_model = listtomodel[SendMessage(h,CB_GETCURSEL,0,0)];
 177.742 +
 177.743 +                        h=GetDlgItem(hdlg,IDC_COMBO2);
 177.744 +                        gfx=listtovid[SendMessage(h,CB_GETCURSEL,0,0)];
 177.745 +
 177.746 +                        h=GetDlgItem(hdlg,IDC_COMBOMEM);
 177.747 +                        mem=mem_list_to_size[SendMessage(h,CB_GETCURSEL,0,0)];
 177.748 +
 177.749 +                        h = GetDlgItem(hdlg, IDC_COMBOCPUM);
 177.750 +                        temp_cpu_m = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.751 +                        h = GetDlgItem(hdlg, IDC_COMBO3);
 177.752 +                        temp_cpu = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.753 +                        fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type >= CPU_i486DX) ? 1 : 0;
 177.754 +                        pclog("newcpu - %i %i %i  %i\n",temp_cpu_m,temp_cpu,fpu,models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type);
 177.755 +
 177.756 +                        if (temp_model != model || gfx!=gfxcard || mem!=mem_size || fpu!=hasfpu)
 177.757 +                        {
 177.758 +                                if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK)
 177.759 +                                {
 177.760 +                                        model = temp_model;
 177.761 +                                        romset = model_getromset();
 177.762 +                                        gfxcard=gfx;
 177.763 +                                        mem_size=mem;
 177.764 +                                        cpu_manufacturer = temp_cpu_m;
 177.765 +                                        cpu = temp_cpu;
 177.766 +                                        
 177.767 +                                        mem_resize();
 177.768 +                                        loadbios();
 177.769 +                                        resetpchard();
 177.770 +                                }
 177.771 +                                else
 177.772 +                                {
 177.773 +                                        EndDialog(hdlg,0);
 177.774 +                                        pause=0;
 177.775 +                                        return TRUE;
 177.776 +                                }
 177.777 +                        }
 177.778 +
 177.779 +                        h=GetDlgItem(hdlg,IDC_COMBOSPD);
 177.780 +                        video_speed = SendMessage(h,CB_GETCURSEL,0,0);
 177.781 +
 177.782 +                        h=GetDlgItem(hdlg,IDC_CHECK3);
 177.783 +                        GAMEBLASTER=SendMessage(h,BM_GETCHECK,0,0);
 177.784 +
 177.785 +                        h=GetDlgItem(hdlg,IDC_CHECK1);
 177.786 +                        FASTDISC=SendMessage(h,BM_GETCHECK,0,0);
 177.787 +
 177.788 +                        h=GetDlgItem(hdlg,IDC_CHECK4);
 177.789 +                        cga_comp=SendMessage(h,BM_GETCHECK,0,0);
 177.790 +
 177.791 +                        cpu_manufacturer = temp_cpu_m;
 177.792 +                        cpu = temp_cpu;
 177.793 +                        cpu_set();
 177.794 +                        
 177.795 +                        h=GetDlgItem(hdlg,IDC_COMBOSND);
 177.796 +                        sbtype=SendMessage(h,CB_GETCURSEL,0,0);
 177.797 +
 177.798 +                        h=GetDlgItem(hdlg,IDC_COMBOCHC);
 177.799 +                        cache=SendMessage(h,CB_GETCURSEL,0,0);
 177.800 +                        mem_updatecache();
 177.801 +                        
 177.802 +                        saveconfig();
 177.803 +
 177.804 +                        speedchanged();
 177.805 +//                        if (romset>2) cpuspeed=1;
 177.806 +//                        setpitclock(clocks[AT?1:0][cpuspeed][0]);
 177.807 +//                        if (cpuspeed) setpitclock(8000000.0);
 177.808 +//                        else          setpitclock(4772728.0);
 177.809 +
 177.810 +                        case IDCANCEL:
 177.811 +                        EndDialog(hdlg,0);
 177.812 +                        pause=0;
 177.813 +                        return TRUE;
 177.814 +                        case IDC_COMBO1:
 177.815 +                        if (HIWORD(wParam) == CBN_SELCHANGE)
 177.816 +                        {
 177.817 +                                h = GetDlgItem(hdlg,IDC_COMBO1);
 177.818 +                                temp_model = listtomodel[SendMessage(h,CB_GETCURSEL,0,0)];
 177.819 +                                
 177.820 +                                /*Enable/disable gfxcard list*/
 177.821 +                                h = GetDlgItem(hdlg, IDC_COMBO2);
 177.822 +                                if (!models[temp_model].fixed_gfxcard)
 177.823 +                                {
 177.824 +                                        EnableWindow(h, TRUE);
 177.825 +                                        SendMessage(h, CB_SETCURSEL, gfxcard, 0);
 177.826 +                                }
 177.827 +                                else
 177.828 +                                        EnableWindow(h, FALSE);
 177.829 +                                
 177.830 +                                /*Rebuild manufacturer list*/
 177.831 +                                h = GetDlgItem(hdlg, IDC_COMBOCPUM);
 177.832 +                                temp_cpu_m = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.833 +                                SendMessage(h, CB_RESETCONTENT, 0, 0);
 177.834 +                                c = 0;
 177.835 +                                while (models[temp_model].cpu[c].cpus != NULL && c < 3)
 177.836 +                                {
 177.837 +                                        SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)models[temp_model].cpu[c].name);
 177.838 +                                        c++;
 177.839 +                                }
 177.840 +                                if (temp_cpu_m >= c) temp_cpu_m = c - 1;
 177.841 +                                SendMessage(h, CB_SETCURSEL, temp_cpu_m, 0);
 177.842 +                                if (c == 1) EnableWindow(h, FALSE);
 177.843 +                                else        EnableWindow(h, TRUE);
 177.844 +
 177.845 +                                /*Rebuild CPU list*/
 177.846 +                                h = GetDlgItem(hdlg, IDC_COMBO3);
 177.847 +                                temp_cpu = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.848 +                                SendMessage(h, CB_RESETCONTENT, 0, 0);
 177.849 +                                c = 0;
 177.850 +                                while (models[temp_model].cpu[temp_cpu_m].cpus[c].cpu_type != -1)
 177.851 +                                {
 177.852 +                                        SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)models[temp_model].cpu[temp_cpu_m].cpus[c].name);
 177.853 +                                        c++;
 177.854 +                                }
 177.855 +                                if (temp_cpu >= c) temp_cpu = c - 1;
 177.856 +                                SendMessage(h, CB_SETCURSEL, temp_cpu, 0);
 177.857 +                        }
 177.858 +                        break;
 177.859 +                        case IDC_COMBOCPUM:
 177.860 +                        if (HIWORD(wParam) == CBN_SELCHANGE)
 177.861 +                        {
 177.862 +                                h = GetDlgItem(hdlg, IDC_COMBO1);
 177.863 +                                temp_model = listtomodel[SendMessage(h, CB_GETCURSEL, 0, 0)];
 177.864 +                                h = GetDlgItem(hdlg, IDC_COMBOCPUM);
 177.865 +                                temp_cpu_m = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.866 +                                
 177.867 +                                /*Rebuild CPU list*/
 177.868 +                                h=GetDlgItem(hdlg, IDC_COMBO3);
 177.869 +                                temp_cpu = SendMessage(h, CB_GETCURSEL, 0, 0);
 177.870 +                                SendMessage(h, CB_RESETCONTENT, 0, 0);
 177.871 +                                c = 0;
 177.872 +                                while (models[temp_model].cpu[temp_cpu_m].cpus[c].cpu_type != -1)
 177.873 +                                {
 177.874 +                                        SendMessage(h,CB_ADDSTRING,0,(LPARAM)(LPCSTR)models[temp_model].cpu[temp_cpu_m].cpus[c].name);
 177.875 +                                        c++;
 177.876 +                                }
 177.877 +                                if (temp_cpu >= c) temp_cpu = c - 1;
 177.878 +                                SendMessage(h, CB_SETCURSEL, temp_cpu, 0);
 177.879 +                        }
 177.880 +                        break;
 177.881 +                }
 177.882 +                break;
 177.883 +
 177.884 +        }
 177.885 +        return FALSE;
 177.886 +}
 177.887 +static char hd_new_name[512];
 177.888 +static int hd_new_spt, hd_new_hpc, hd_new_cyl;
 177.889 +
 177.890 +BOOL CALLBACK hdnewdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
 177.891 +{
 177.892 +        char s[260];
 177.893 +        HWND h;
 177.894 +        int c;
 177.895 +        PcemHDC hd[2];
 177.896 +        int changeddrv=0;
 177.897 +        FILE *f;
 177.898 +        uint8_t buf[512];
 177.899 +        switch (message)
 177.900 +        {
 177.901 +                case WM_INITDIALOG:
 177.902 +                h = GetDlgItem(hdlg, IDC_EDIT1);
 177.903 +                sprintf(s, "%i", 63);
 177.904 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
 177.905 +                h = GetDlgItem(hdlg, IDC_EDIT2);
 177.906 +                sprintf(s, "%i", 16);
 177.907 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
 177.908 +                h = GetDlgItem(hdlg, IDC_EDIT3);
 177.909 +                sprintf(s, "%i", 511);
 177.910 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
 177.911 +
 177.912 +                h = GetDlgItem(hdlg, IDC_EDITC);
 177.913 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)"");
 177.914 +                
 177.915 +                h = GetDlgItem(hdlg, IDC_TEXT1);
 177.916 +                sprintf(s, "Size : %imb", (((511*16*63)*512)/1024)/1024);
 177.917 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
 177.918 +
 177.919 +                return TRUE;
 177.920 +                case WM_COMMAND:
 177.921 +                switch (LOWORD(wParam))
 177.922 +                {
 177.923 +                        case IDOK:
 177.924 +                        h = GetDlgItem(hdlg, IDC_EDITC);
 177.925 +                        SendMessage(h, WM_GETTEXT, 511, (LPARAM)hd_new_name);
 177.926 +                        if (!hd_new_name[0])
 177.927 +                        {
 177.928 +                                MessageBox(ghwnd,"Please enter a valid filename","PCem error",MB_OK);
 177.929 +                                return TRUE;
 177.930 +                        }
 177.931 +                        h = GetDlgItem(hdlg, IDC_EDIT1);
 177.932 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
 177.933 +                        sscanf(s, "%i", &hd_new_spt);
 177.934 +                        h = GetDlgItem(hdlg, IDC_EDIT2);
 177.935 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
 177.936 +                        sscanf(s, "%i", &hd_new_hpc);
 177.937 +                        h = GetDlgItem(hdlg, IDC_EDIT3);
 177.938 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
 177.939 +                        sscanf(s, "%i", &hd_new_cyl);
 177.940 +                        
 177.941 +                        if (hd_new_spt > 63)
 177.942 +                        {
 177.943 +                                MessageBox(ghwnd,"Drive has too many sectors (maximum is 63)","PCem error",MB_OK);
 177.944 +                                return TRUE;
 177.945 +                        }
 177.946 +                        if (hd_new_hpc > 128)
 177.947 +                        {
 177.948 +                                MessageBox(ghwnd,"Drive has too many heads (maximum is 128)","PCem error",MB_OK);
 177.949 +                                return TRUE;
 177.950 +                        }
 177.951 +                        if (hd_new_cyl > 16383)
 177.952 +                        {
 177.953 +                                MessageBox(ghwnd,"Drive has too many cylinders (maximum is 16383)","PCem error",MB_OK);
 177.954 +                                return TRUE;
 177.955 +                        }
 177.956 +                        
 177.957 +                        f = fopen64(hd_new_name, "wb");
 177.958 +                        if (!f)
 177.959 +                        {
 177.960 +                                MessageBox(ghwnd,"Can't open file for write","PCem error",MB_OK);
 177.961 +                                return TRUE;
 177.962 +                        }
 177.963 +                        memset(buf, 0, 512);
 177.964 +                        for (c = 0; c < (hd_new_cyl * hd_new_hpc * hd_new_spt); c++)
 177.965 +                            fwrite(buf, 512, 1, f);
 177.966 +                        fclose(f);
 177.967 +                        
 177.968 +                        MessageBox(ghwnd,"Remember to partition and format the new drive","PCem",MB_OK);
 177.969 +                        
 177.970 +                        EndDialog(hdlg,1);
 177.971 +                        return TRUE;
 177.972 +                        case IDCANCEL:
 177.973 +                        EndDialog(hdlg,0);
 177.974 +                        return TRUE;
 177.975 +
 177.976 +                        case IDC_CFILE:
 177.977 +                        if (!getsfile(hdlg, "Hard disc image (*.IMG)\0*.IMG\0All files (*.*)\0*.*\0", ""))
 177.978 +                        {
 177.979 +                                h = GetDlgItem(hdlg, IDC_EDITC);
 177.980 +                                SendMessage(h, WM_SETTEXT, 0, (LPARAM)openfilestring);
 177.981 +                        }
 177.982 +                        return TRUE;
 177.983 +                        
 177.984 +                        case IDC_EDIT1: case IDC_EDIT2: case IDC_EDIT3:
 177.985 +                        h=GetDlgItem(hdlg,IDC_EDIT1);
 177.986 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
 177.987 +                        sscanf(s,"%i",&hd[0].spt);
 177.988 +                        h=GetDlgItem(hdlg,IDC_EDIT2);
 177.989 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
 177.990 +                        sscanf(s,"%i",&hd[0].hpc);
 177.991 +                        h=GetDlgItem(hdlg,IDC_EDIT3);
 177.992 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
 177.993 +                        sscanf(s,"%i",&hd[0].tracks);
 177.994 +
 177.995 +                        h=GetDlgItem(hdlg,IDC_TEXT1);
 177.996 +                        sprintf(s,"Size : %imb",(((((uint64_t)hd[0].tracks*(uint64_t)hd[0].hpc)*(uint64_t)hd[0].spt)*512)/1024)/1024);
 177.997 +                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
 177.998 +                        return TRUE;
 177.999 +                }
177.1000 +                break;
177.1001 +
177.1002 +        }
177.1003 +        return FALSE;
177.1004 +}
177.1005 +
177.1006 +BOOL CALLBACK hdsizedlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
177.1007 +{
177.1008 +        char s[260];
177.1009 +        HWND h;
177.1010 +        int c;
177.1011 +        PcemHDC hd[2];
177.1012 +        int changeddrv=0;
177.1013 +        FILE *f;
177.1014 +        uint8_t buf[512];
177.1015 +        switch (message)
177.1016 +        {
177.1017 +                case WM_INITDIALOG:
177.1018 +                h = GetDlgItem(hdlg, IDC_EDIT1);
177.1019 +                sprintf(s, "%i", hd_new_spt);
177.1020 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
177.1021 +                h = GetDlgItem(hdlg, IDC_EDIT2);
177.1022 +                sprintf(s, "%i", hd_new_hpc);
177.1023 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
177.1024 +                h = GetDlgItem(hdlg, IDC_EDIT3);
177.1025 +                sprintf(s, "%i", hd_new_cyl);
177.1026 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
177.1027 +
177.1028 +                h = GetDlgItem(hdlg, IDC_TEXT1);
177.1029 +                sprintf(s, "Size : %imb", ((((uint64_t)hd_new_spt*(uint64_t)hd_new_hpc*(uint64_t)hd_new_cyl)*512)/1024)/1024);
177.1030 +                SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
177.1031 +
177.1032 +                return TRUE;
177.1033 +                case WM_COMMAND:
177.1034 +                switch (LOWORD(wParam))
177.1035 +                {
177.1036 +                        case IDOK:
177.1037 +                        h = GetDlgItem(hdlg, IDC_EDIT1);
177.1038 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
177.1039 +                        sscanf(s, "%i", &hd_new_spt);
177.1040 +                        h = GetDlgItem(hdlg, IDC_EDIT2);
177.1041 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
177.1042 +                        sscanf(s, "%i", &hd_new_hpc);
177.1043 +                        h = GetDlgItem(hdlg, IDC_EDIT3);
177.1044 +                        SendMessage(h, WM_GETTEXT, 255, (LPARAM)s);
177.1045 +                        sscanf(s, "%i", &hd_new_cyl);
177.1046 +                        
177.1047 +                        if (hd_new_spt > 63)
177.1048 +                        {
177.1049 +                                MessageBox(ghwnd,"Drive has too many sectors (maximum is 63)","PCem error",MB_OK);
177.1050 +                                return TRUE;
177.1051 +                        }
177.1052 +                        if (hd_new_hpc > 128)
177.1053 +                        {
177.1054 +                                MessageBox(ghwnd,"Drive has too many heads (maximum is 128)","PCem error",MB_OK);
177.1055 +                                return TRUE;
177.1056 +                        }
177.1057 +                        if (hd_new_cyl > 16383)
177.1058 +                        {
177.1059 +                                MessageBox(ghwnd,"Drive has too many cylinders (maximum is 16383)","PCem error",MB_OK);
177.1060 +                                return TRUE;
177.1061 +                        }
177.1062 +                        
177.1063 +                        EndDialog(hdlg,1);
177.1064 +                        return TRUE;
177.1065 +                        case IDCANCEL:
177.1066 +                        EndDialog(hdlg,0);
177.1067 +                        return TRUE;
177.1068 +
177.1069 +                        case IDC_EDIT1: case IDC_EDIT2: case IDC_EDIT3:
177.1070 +                        h=GetDlgItem(hdlg,IDC_EDIT1);
177.1071 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1072 +                        sscanf(s,"%i",&hd[0].spt);
177.1073 +                        h=GetDlgItem(hdlg,IDC_EDIT2);
177.1074 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1075 +                        sscanf(s,"%i",&hd[0].hpc);
177.1076 +                        h=GetDlgItem(hdlg,IDC_EDIT3);
177.1077 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1078 +                        sscanf(s,"%i",&hd[0].tracks);
177.1079 +
177.1080 +                        h=GetDlgItem(hdlg,IDC_TEXT1);
177.1081 +                        sprintf(s,"Size : %imb",(((((uint64_t)hd[0].tracks*(uint64_t)hd[0].hpc)*(uint64_t)hd[0].spt)*512)/1024)/1024);
177.1082 +                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1083 +                        return TRUE;
177.1084 +                }
177.1085 +                break;
177.1086 +
177.1087 +        }
177.1088 +        return FALSE;
177.1089 +}
177.1090 +
177.1091 +static int hd_changed = 0;
177.1092 +BOOL CALLBACK hdconfdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
177.1093 +{
177.1094 +        char s[260];
177.1095 +        HWND h;
177.1096 +        int c;
177.1097 +        PcemHDC hd[2];
177.1098 +        int changeddrv=0;
177.1099 +        FILE *f;
177.1100 +        off64_t sz;
177.1101 +        switch (message)
177.1102 +        {
177.1103 +                case WM_INITDIALOG:
177.1104 +                pause=1;
177.1105 +                hd[0]=hdc[0];
177.1106 +                hd[1]=hdc[1];
177.1107 +                hd_changed = 0;
177.1108 +                
177.1109 +                h=GetDlgItem(hdlg,IDC_EDIT1);
177.1110 +                sprintf(s,"%i",hdc[0].spt);
177.1111 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1112 +                h=GetDlgItem(hdlg,IDC_EDIT2);
177.1113 +                sprintf(s,"%i",hdc[0].hpc);
177.1114 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1115 +                h=GetDlgItem(hdlg,IDC_EDIT3);
177.1116 +                sprintf(s,"%i",hdc[0].tracks);
177.1117 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1118 +                h=GetDlgItem(hdlg,IDC_EDITC);
177.1119 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)ide_fn[0]);
177.1120 +
177.1121 +                h=GetDlgItem(hdlg,IDC_EDIT4);
177.1122 +                sprintf(s,"%i",hdc[1].spt);
177.1123 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1124 +                h=GetDlgItem(hdlg,IDC_EDIT5);
177.1125 +                sprintf(s,"%i",hdc[1].hpc);
177.1126 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1127 +                h=GetDlgItem(hdlg,IDC_EDIT6);
177.1128 +                sprintf(s,"%i",hdc[1].tracks);
177.1129 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1130 +                h=GetDlgItem(hdlg,IDC_EDITD);
177.1131 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)ide_fn[1]);
177.1132 +                
177.1133 +                h=GetDlgItem(hdlg,IDC_TEXT1);
177.1134 +                sprintf(s,"Size : %imb",(((((uint64_t)hd[0].tracks*(uint64_t)hd[0].hpc)*(uint64_t)hd[0].spt)*512)/1024)/1024);
177.1135 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1136 +
177.1137 +                h=GetDlgItem(hdlg,IDC_TEXT2);
177.1138 +                sprintf(s,"Size : %imb",(((((uint64_t)hd[1].tracks*(uint64_t)hd[1].hpc)*(uint64_t)hd[1].spt)*512)/1024)/1024);
177.1139 +                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1140 +                return TRUE;
177.1141 +                case WM_COMMAND:
177.1142 +                switch (LOWORD(wParam))
177.1143 +                {
177.1144 +                        case IDOK:
177.1145 +                        if (hd_changed)
177.1146 +                        {                     
177.1147 +                                if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK)
177.1148 +                                {
177.1149 +                                        h=GetDlgItem(hdlg,IDC_EDIT1);
177.1150 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1151 +                                        sscanf(s,"%i",&hd[0].spt);
177.1152 +                                        h=GetDlgItem(hdlg,IDC_EDIT2);
177.1153 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1154 +                                        sscanf(s,"%i",&hd[0].hpc);
177.1155 +                                        h=GetDlgItem(hdlg,IDC_EDIT3);
177.1156 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1157 +                                        sscanf(s,"%i",&hd[0].tracks);
177.1158 +                                        h=GetDlgItem(hdlg,IDC_EDITC);
177.1159 +                                        SendMessage(h,WM_GETTEXT,511,(LPARAM)ide_fn[0]);
177.1160 +
177.1161 +                                        h=GetDlgItem(hdlg,IDC_EDIT4);
177.1162 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1163 +                                        sscanf(s,"%i",&hd[1].spt);
177.1164 +                                        h=GetDlgItem(hdlg,IDC_EDIT5);
177.1165 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1166 +                                        sscanf(s,"%i",&hd[1].hpc);
177.1167 +                                        h=GetDlgItem(hdlg,IDC_EDIT6);
177.1168 +                                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1169 +                                        sscanf(s,"%i",&hd[1].tracks);
177.1170 +                                        h=GetDlgItem(hdlg,IDC_EDITD);
177.1171 +                                        SendMessage(h,WM_GETTEXT,511,(LPARAM)ide_fn[1]);
177.1172 +                                        
177.1173 +                                        hdc[0] = hd[0];
177.1174 +                                        hdc[1] = hd[1];
177.1175 +
177.1176 +                                        saveconfig();
177.1177 +                                                                                
177.1178 +                                        resetpchard();
177.1179 +                                }                                
177.1180 +                        }
177.1181 +                        case IDCANCEL:
177.1182 +                        EndDialog(hdlg,0);
177.1183 +                        pause=0;
177.1184 +                        return TRUE;
177.1185 +
177.1186 +                        case IDC_CNEW:
177.1187 +                        if (DialogBox(hinstance,TEXT("HdNewDlg"),hdlg,hdnewdlgproc) == 1)
177.1188 +                        {
177.1189 +                                h=GetDlgItem(hdlg,IDC_EDIT1);
177.1190 +                                sprintf(s,"%i",hd_new_spt);
177.1191 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1192 +                                h=GetDlgItem(hdlg,IDC_EDIT2);
177.1193 +                                sprintf(s,"%i",hd_new_hpc);
177.1194 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1195 +                                h=GetDlgItem(hdlg,IDC_EDIT3);
177.1196 +                                sprintf(s,"%i",hd_new_cyl);
177.1197 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1198 +                                h=GetDlgItem(hdlg,IDC_EDITC);
177.1199 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)hd_new_name);
177.1200 +
177.1201 +                                h=GetDlgItem(hdlg,IDC_TEXT1);
177.1202 +                                sprintf(s,"Size : %imb",(((((uint64_t)hd_new_cyl*(uint64_t)hd_new_hpc)*(uint64_t)hd_new_spt)*512)/1024)/1024);
177.1203 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1204 +
177.1205 +                                hd_changed = 1;
177.1206 +                        }                              
177.1207 +                        return TRUE;
177.1208 +                        
177.1209 +                        case IDC_CFILE:
177.1210 +                        if (!getfile(hdlg, "Hard disc image (*.IMG)\0*.IMG\0All files (*.*)\0*.*\0", ""))
177.1211 +                        {
177.1212 +                                f = fopen64(openfilestring, "rb");
177.1213 +                                if (!f)
177.1214 +                                {
177.1215 +                                        MessageBox(ghwnd,"Can't open file for read","PCem error",MB_OK);
177.1216 +                                        return TRUE;
177.1217 +                                }
177.1218 +                                fseeko64(f, -1, SEEK_END);
177.1219 +                                sz = ftello64(f) + 1;
177.1220 +                                fclose(f);
177.1221 +                                hd_new_spt = 63;
177.1222 +                                hd_new_hpc = 16;
177.1223 +                                hd_new_cyl = ((sz / 512) / 16) / 63;
177.1224 +                                
177.1225 +                                if (DialogBox(hinstance,TEXT("HdSizeDlg"),hdlg,hdsizedlgproc) == 1)
177.1226 +                                {
177.1227 +                                        h=GetDlgItem(hdlg,IDC_EDIT1);
177.1228 +                                        sprintf(s,"%i",hd_new_spt);
177.1229 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1230 +                                        h=GetDlgItem(hdlg,IDC_EDIT2);
177.1231 +                                        sprintf(s,"%i",hd_new_hpc);
177.1232 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1233 +                                        h=GetDlgItem(hdlg,IDC_EDIT3);
177.1234 +                                        sprintf(s,"%i",hd_new_cyl);
177.1235 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1236 +                                        h=GetDlgItem(hdlg,IDC_EDITC);
177.1237 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)openfilestring);
177.1238 +
177.1239 +                                        h=GetDlgItem(hdlg,IDC_TEXT1);
177.1240 +                                        sprintf(s,"Size : %imb",(((((uint64_t)hd_new_cyl*(uint64_t)hd_new_hpc)*(uint64_t)hd_new_spt)*512)/1024)/1024);
177.1241 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1242 +        
177.1243 +                                        hd_changed = 1;
177.1244 +                                }
177.1245 +                        }
177.1246 +                        return TRUE;
177.1247 +                                
177.1248 +                        case IDC_DNEW:
177.1249 +                        if (DialogBox(hinstance,TEXT("HdNewDlg"),hdlg,hdnewdlgproc) == 1)
177.1250 +                        {
177.1251 +                                h=GetDlgItem(hdlg,IDC_EDIT4);
177.1252 +                                sprintf(s,"%i",hd_new_spt);
177.1253 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1254 +                                h=GetDlgItem(hdlg,IDC_EDIT5);
177.1255 +                                sprintf(s,"%i",hd_new_hpc);
177.1256 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1257 +                                h=GetDlgItem(hdlg,IDC_EDIT6);
177.1258 +                                sprintf(s,"%i",hd_new_cyl);
177.1259 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1260 +                                h=GetDlgItem(hdlg,IDC_EDITD);
177.1261 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)hd_new_name);
177.1262 +
177.1263 +                                h=GetDlgItem(hdlg,IDC_TEXT2);
177.1264 +                                sprintf(s,"Size : %imb",(((((uint64_t)hd_new_cyl*(uint64_t)hd_new_hpc)*(uint64_t)hd_new_spt)*512)/1024)/1024);
177.1265 +                                SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1266 +
177.1267 +                                hd_changed = 1;
177.1268 +                        }                              
177.1269 +                        return TRUE;
177.1270 +                        
177.1271 +                        case IDC_DFILE:
177.1272 +                        if (!getfile(hdlg, "Hard disc image (*.IMG)\0*.IMG\0All files (*.*)\0*.*\0", ""))
177.1273 +                        {
177.1274 +                                f = fopen64(openfilestring, "rb");
177.1275 +                                if (!f)
177.1276 +                                {
177.1277 +                                        MessageBox(ghwnd,"Can't open file for read","PCem error",MB_OK);
177.1278 +                                        return TRUE;
177.1279 +                                }
177.1280 +                                fseeko64(f, -1, SEEK_END);
177.1281 +                                sz = ftello64(f) + 1;
177.1282 +                                fclose(f);
177.1283 +                                hd_new_spt = 63;
177.1284 +                                hd_new_hpc = 16;
177.1285 +                                hd_new_cyl = ((sz / 512) / 16) / 63;
177.1286 +                                
177.1287 +                                if (DialogBox(hinstance,TEXT("HdSizeDlg"),hdlg,hdsizedlgproc) == 1)
177.1288 +                                {
177.1289 +                                        h=GetDlgItem(hdlg,IDC_EDIT4);
177.1290 +                                        sprintf(s,"%i",hd_new_spt);
177.1291 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1292 +                                        h=GetDlgItem(hdlg,IDC_EDIT5);
177.1293 +                                        sprintf(s,"%i",hd_new_hpc);
177.1294 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1295 +                                        h=GetDlgItem(hdlg,IDC_EDIT6);
177.1296 +                                        sprintf(s,"%i",hd_new_cyl);
177.1297 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1298 +                                        h=GetDlgItem(hdlg,IDC_EDITD);
177.1299 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)openfilestring);
177.1300 +
177.1301 +                                        h=GetDlgItem(hdlg,IDC_TEXT2);
177.1302 +                                        sprintf(s,"Size : %imb",(((((uint64_t)hd_new_cyl*(uint64_t)hd_new_hpc)*(uint64_t)hd_new_spt)*512)/1024)/1024);
177.1303 +                                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1304 +        
177.1305 +                                        hd_changed = 1;
177.1306 +                                }
177.1307 +                        }
177.1308 +                        return TRUE;
177.1309 +
177.1310 +                        case IDC_EDIT1: case IDC_EDIT2: case IDC_EDIT3:
177.1311 +                        h=GetDlgItem(hdlg,IDC_EDIT1);
177.1312 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1313 +                        sscanf(s,"%i",&hd[0].spt);
177.1314 +                        h=GetDlgItem(hdlg,IDC_EDIT2);
177.1315 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1316 +                        sscanf(s,"%i",&hd[0].hpc);
177.1317 +                        h=GetDlgItem(hdlg,IDC_EDIT3);
177.1318 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1319 +                        sscanf(s,"%i",&hd[0].tracks);
177.1320 +
177.1321 +                        h=GetDlgItem(hdlg,IDC_TEXT1);
177.1322 +                        sprintf(s,"Size : %imb",((((hd[0].tracks*hd[0].hpc)*hd[0].spt)*512)/1024)/1024);
177.1323 +                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1324 +                        return TRUE;
177.1325 +
177.1326 +                        case IDC_EDIT4: case IDC_EDIT5: case IDC_EDIT6:
177.1327 +                        h=GetDlgItem(hdlg,IDC_EDIT4);
177.1328 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1329 +                        sscanf(s,"%i",&hd[1].spt);
177.1330 +                        h=GetDlgItem(hdlg,IDC_EDIT5);
177.1331 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1332 +                        sscanf(s,"%i",&hd[1].hpc);
177.1333 +                        h=GetDlgItem(hdlg,IDC_EDIT6);
177.1334 +                        SendMessage(h,WM_GETTEXT,255,(LPARAM)s);
177.1335 +                        sscanf(s,"%i",&hd[1].tracks);
177.1336 +
177.1337 +                        h=GetDlgItem(hdlg,IDC_TEXT2);
177.1338 +                        sprintf(s,"Size : %imb",((((hd[1].tracks*hd[1].hpc)*hd[1].spt)*512)/1024)/1024);
177.1339 +                        SendMessage(h,WM_SETTEXT,0,(LPARAM)s);
177.1340 +                        return TRUE;
177.1341 +                }
177.1342 +                break;
177.1343 +
177.1344 +        }
177.1345 +        return FALSE;
177.1346 +}
177.1347 +
177.1348 +BOOL CALLBACK statusdlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
177.1349 +{
177.1350 +        HWND h;
177.1351 +        int c;
177.1352 +        int egasp;
177.1353 +        char s[256];
177.1354 +        switch (message)
177.1355 +        {
177.1356 +                case WM_INITDIALOG:
177.1357 +                statusopen=1;
177.1358 +                case WM_USER:
177.1359 +                sprintf(s,"CPU speed : %f MIPS",mips);
177.1360 +                SendDlgItemMessage(hdlg,IDC_STEXT1,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1361 +                sprintf(s,"FPU speed : %f MFLOPS",flops);
177.1362 +                SendDlgItemMessage(hdlg,IDC_STEXT2,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1363 +                sprintf(s,"Cache misses (read) : %i/sec",sreadlnum);
177.1364 +                SendDlgItemMessage(hdlg,IDC_STEXT3,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1365 +                sprintf(s,"Cache misses (write) : %i/sec",swritelnum);
177.1366 +                SendDlgItemMessage(hdlg,IDC_STEXT4,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1367 +                sprintf(s,"Video throughput (read) : %i bytes/sec",segareads);
177.1368 +                SendDlgItemMessage(hdlg,IDC_STEXT5,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1369 +                sprintf(s,"Video throughput (write) : %i bytes/sec",segawrites);
177.1370 +                SendDlgItemMessage(hdlg,IDC_STEXT6,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1371 +                egasp=(slowega)?egacycles:egacycles2;
177.1372 +                sprintf(s,"Effective clockspeed : %iHz",clockrate-(sreadlnum*memwaitstate)-(swritelnum*memwaitstate)- scycles_lost);
177.1373 +//                pclog("%i : %i %i %i %i : %i %i\n",clockrate,sreadlnum*memwaitstate,swritelnum*memwaitstate,segareads*egasp,segawrites*egasp,segawrites,egasp);
177.1374 +                SendDlgItemMessage(hdlg,IDC_STEXT7,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1375 +                sprintf(s,"Timer 0 frequency : %fHz",pit_timer0_freq());
177.1376 +                SendDlgItemMessage(hdlg,IDC_STEXT8,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1377 +                if (chain4) sprintf(s,"VGA chained (possibly mode 13h)");
177.1378 +                else        sprintf(s,"VGA unchained (possibly mode-X)");
177.1379 +                SendDlgItemMessage(hdlg,IDC_STEXT9,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1380 +                if (!video_bpp) sprintf(s,"VGA in text mode");
177.1381 +                else            sprintf(s,"VGA colour depth : %i bpp", video_bpp);
177.1382 +                SendDlgItemMessage(hdlg,IDC_STEXT10,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1383 +                sprintf(s,"VGA resolution : %i x %i", video_res_x, video_res_y);
177.1384 +                SendDlgItemMessage(hdlg,IDC_STEXT11,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1385 +                sprintf(s,"SB frequency : %i Hz",sb_freq);
177.1386 +                SendDlgItemMessage(hdlg,IDC_STEXT12,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1387 +                sprintf(s,"Video refresh rate : %i Hz", emu_fps);
177.1388 +                SendDlgItemMessage(hdlg,IDC_STEXT13,WM_SETTEXT,(WPARAM)NULL,(LPARAM)s);
177.1389 +                return TRUE;
177.1390 +                case WM_COMMAND:
177.1391 +                switch (LOWORD(wParam))
177.1392 +                {
177.1393 +                        case IDOK:
177.1394 +                        case IDCANCEL:
177.1395 +                        statusopen=0;
177.1396 +                        EndDialog(hdlg,0);
177.1397 +                        return TRUE;
177.1398 +                }
177.1399 +                break;
177.1400 +        }
177.1401 +        return FALSE;
177.1402 +}
177.1403 +
177.1404 +
177.1405 +HHOOK hKeyboardHook;
177.1406 +
177.1407 +LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
177.1408 +{
177.1409 +    if (nCode < 0 || nCode != HC_ACTION || !mousecapture) return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam); 
177.1410 +	
177.1411 +	KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
177.1412 +
177.1413 +    if(p->vkCode==VK_TAB && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab
177.1414 +    if(p->vkCode==VK_SPACE && p->flags & LLKHF_ALTDOWN) return 1; //disable alt-tab    
177.1415 +	if((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)) return 1;//disable windows keys
177.1416 +	if (p->vkCode == VK_ESCAPE && p->flags & LLKHF_ALTDOWN) return 1;//disable alt-escape
177.1417 +	BOOL bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);//checks ctrl key pressed
177.1418 +	if (p->vkCode == VK_ESCAPE && bControlKeyDown) return 1; //disable ctrl-escape
177.1419 +	
177.1420 +	return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam );
177.1421 +}
177.1422 +
177.1423 +LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
177.1424 +{
177.1425 +        HMENU hmenu;
177.1426 +        RECT rect;
177.1427 +        int c;
177.1428 +        int x, y;
177.1429 +        POINT po;
177.1430 +//        pclog("Message %i %08X\n",message,message);
177.1431 +        switch (message)
177.1432 +        {
177.1433 +                case WM_CREATE:
177.1434 +                SetTimer(hwnd, TIMER_1SEC, 1000, NULL);
177.1435 +                hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL,  LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
177.1436 +                break;
177.1437 +                
177.1438 +                case WM_COMMAND:
177.1439 +//                        pclog("WM_COMMAND %i\n",LOWORD(wParam));
177.1440 +                hmenu=GetMenu(hwnd);
177.1441 +                switch (LOWORD(wParam))
177.1442 +                {
177.1443 +                        case IDM_FILE_RESET:
177.1444 +                        pause=1;
177.1445 +                        Sleep(100);
177.1446 +                        resetpc();
177.1447 +                        pause=0;
177.1448 +                        drawit=1;
177.1449 +                        break;
177.1450 +                        case IDM_FILE_HRESET:
177.1451 +                        pause=1;
177.1452 +                        Sleep(100);
177.1453 +                        resetpchard();
177.1454 +                        pause=0;
177.1455 +                        drawit=1;
177.1456 +                        break;
177.1457 +                        case IDM_FILE_EXIT:
177.1458 +                        PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
177.1459 +                        break;
177.1460 +                        case IDM_DISC_A:
177.1461 +                        if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[0]))
177.1462 +                        {
177.1463 +                                savedisc(0);
177.1464 +                                loaddisc(0,openfilestring);
177.1465 +                                saveconfig();
177.1466 +                        }
177.1467 +                        break;
177.1468 +                        case IDM_DISC_B:
177.1469 +                        if (!getfile(hwnd,"Disc image (*.IMG;*.IMA)\0*.IMG;*.IMA\0All files (*.*)\0*.*\0",discfns[1]))
177.1470 +                        {
177.1471 +                                savedisc(1);
177.1472 +                                loaddisc(1,openfilestring);
177.1473 +                                saveconfig();
177.1474 +                        }
177.1475 +                        break;
177.1476 +                        case IDM_EJECT_A:
177.1477 +                        savedisc(0);
177.1478 +                        ejectdisc(0);
177.1479 +                        saveconfig();
177.1480 +                        break;
177.1481 +                        case IDM_EJECT_B:
177.1482 +                        savedisc(1);
177.1483 +                        ejectdisc(1);
177.1484 +                        saveconfig();
177.1485 +                        break;
177.1486 +                        case IDM_HDCONF:
177.1487 +                        DialogBox(hinstance,TEXT("HdConfDlg"),hwnd,hdconfdlgproc);
177.1488 +                        break;
177.1489 +                        case IDM_CONFIG:
177.1490 +                        DialogBox(hinstance,TEXT("ConfigureDlg"),hwnd,configdlgproc);
177.1491 +                        break;
177.1492 +                        case IDM_STATUS:
177.1493 +                        statushwnd=CreateDialog(hinstance,TEXT("StatusDlg"),hwnd,statusdlgproc);
177.1494 +                        ShowWindow(statushwnd,SW_SHOW);
177.1495 +                        break;
177.1496 +                        
177.1497 +                        case IDM_VID_RESIZE:
177.1498 +                        vid_resize=!vid_resize;
177.1499 +                        CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)?MF_CHECKED:MF_UNCHECKED);
177.1500 +                        if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE);
177.1501 +                        else            SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE);
177.1502 +                        GetWindowRect(hwnd,&rect);
177.1503 +                        SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED);
177.1504 +                        saveconfig();
177.1505 +                        break;
177.1506 +                        case IDM_KEY_ALLEGRO: case IDM_KEY_WINDOWS:
177.1507 +                        CheckMenuItem(hmenu,LOWORD(wParam),MF_CHECKED);
177.1508 +                        CheckMenuItem(hmenu,LOWORD(wParam)^1,MF_UNCHECKED);
177.1509 +//                        if (kb_win && LOWORD(wParam)==IDM_KEY_ALLEGRO) install_keyboard();
177.1510 +//                        if (!kb_win && LOWORD(wParam)==IDM_KEY_WINDOWS) remove_keyboard();
177.1511 +                        kb_win=LOWORD(wParam)-IDM_KEY_ALLEGRO;
177.1512 +                        break;
177.1513 +                        
177.1514 +                        case IDM_CDROM_DISABLED:
177.1515 +                        if (cdrom_enabled)
177.1516 +                        {
177.1517 +                                if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
177.1518 +                                   break;
177.1519 +                        }   
177.1520 +                        CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
177.1521 +                        CheckMenuItem(hmenu, IDM_CDROM_DISABLED,           MF_CHECKED);
177.1522 +                        CheckMenuItem(hmenu, IDM_CDROM_EMPTY,              MF_UNCHECKED);
177.1523 +                        if (cdrom_enabled)
177.1524 +                        {
177.1525 +                                cdrom_enabled = 0;                                             
177.1526 +                                saveconfig();
177.1527 +                                resetpchard();
177.1528 +                        }
177.1529 +                        break;
177.1530 +                        
177.1531 +                        case IDM_CDROM_EMPTY:
177.1532 +                        if (!cdrom_enabled)
177.1533 +                        {
177.1534 +                                if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
177.1535 +                                   break;
177.1536 +                        }                        
177.1537 +                        atapi->exit();
177.1538 +                        ioctl_open(0);
177.1539 +                        CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
177.1540 +                        CheckMenuItem(hmenu, IDM_CDROM_DISABLED,           MF_UNCHECKED);
177.1541 +                        cdrom_drive=0;
177.1542 +                        CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED);
177.1543 +                        saveconfig();
177.1544 +                        if (!cdrom_enabled)
177.1545 +                        {
177.1546 +                                cdrom_enabled = 1;
177.1547 +                                saveconfig();
177.1548 +                                resetpchard();
177.1549 +                        }
177.1550 +                        break;
177.1551 +                        default:
177.1552 +                        if (LOWORD(wParam)>=IDM_CDROM_REAL && LOWORD(wParam)<(IDM_CDROM_REAL+100))
177.1553 +                        {
177.1554 +                                if (!cdrom_enabled)
177.1555 +                                {
177.1556 +                                        if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL) != IDOK)
177.1557 +                                           break;
177.1558 +                                }         
177.1559 +                                atapi->exit();
177.1560 +                                ioctl_open(LOWORD(wParam)-IDM_CDROM_REAL);
177.1561 +                                CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED);
177.1562 +                                CheckMenuItem(hmenu, IDM_CDROM_DISABLED,           MF_UNCHECKED);
177.1563 +                                cdrom_drive = LOWORD(wParam) - IDM_CDROM_REAL;
177.1564 +                                CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED);
177.1565 +                                saveconfig();
177.1566 +                                if (!cdrom_enabled)
177.1567 +                                {
177.1568 +                                        cdrom_enabled = 1;
177.1569 +                                        saveconfig();
177.1570 +                                        resetpchard();
177.1571 +                                }
177.1572 +                        }
177.1573 +                        break;
177.1574 +                }
177.1575 +                return 0;
177.1576 +                
177.1577 +                case WM_SETFOCUS:
177.1578 +                infocus=1;
177.1579 +                drawit=0;
177.1580 + //               QueryPerformanceCounter(&counter_posold);
177.1581 +//                ResetEvent(frameobject);
177.1582 +//                restoresound();
177.1583 +//                pclog("Set focus!\n");
177.1584 +                break;
177.1585 +                case WM_KILLFOCUS:
177.1586 +                infocus=0;
177.1587 +                if (mousecapture)
177.1588 +                {
177.1589 +                        ClipCursor(&oldclip);
177.1590 +                        ShowCursor(TRUE);
177.1591 +                        mousecapture=0;
177.1592 +                }
177.1593 +//                silencesound();
177.1594 +//                pclog("Lost focus!\n");
177.1595 +                break;
177.1596 +
177.1597 +                case WM_LBUTTONUP:
177.1598 +                if (!mousecapture)
177.1599 +                {
177.1600 +                        GetClipCursor(&oldclip);
177.1601 +                        GetWindowRect(hwnd,&pcclip);
177.1602 +                        pcclip.left+=GetSystemMetrics(SM_CXFIXEDFRAME)+10;
177.1603 +                        pcclip.right-=GetSystemMetrics(SM_CXFIXEDFRAME)+10;
177.1604 +                        pcclip.top+=GetSystemMetrics(SM_CXFIXEDFRAME)+GetSystemMetrics(SM_CYMENUSIZE)+GetSystemMetrics(SM_CYCAPTION)+10;
177.1605 +                        pcclip.bottom-=GetSystemMetrics(SM_CXFIXEDFRAME)+10;
177.1606 +                        ClipCursor(&pcclip);
177.1607 +                        mousecapture=1;
177.1608 +                        ShowCursor(FALSE);
177.1609 +                }
177.1610 +                break;
177.1611 +
177.1612 +                case WM_ENTERMENULOOP:
177.1613 +//                if (key[KEY_ALT] || key[KEY_ALTGR]) return 0;
177.1614 +                break;
177.1615 +
177.1616 +                case WM_SIZE:
177.1617 +                winsizex=lParam&0xFFFF;
177.1618 +                winsizey=lParam>>16;
177.1619 +//                startblit();
177.1620 +//                d3d_resize(winsizex, winsizey);
177.1621 +//                endblit();
177.1622 +                break;
177.1623 +
177.1624 +                case WM_TIMER:
177.1625 +                if (wParam == TIMER_1SEC)
177.1626 +                   onesec();
177.1627 +                break;
177.1628 +
177.1629 +                case WM_KEYDOWN:
177.1630 +                case WM_SYSKEYDOWN:
177.1631 +                case WM_KEYUP:
177.1632 +                case WM_SYSKEYUP:
177.1633 +//                if (mousecapture)
177.1634 +                   return 0;
177.1635 +//                return DefWindowProc (hwnd, message, wParam, lParam);
177.1636 +                
177.1637 +                case WM_DESTROY:
177.1638 +                UnhookWindowsHookEx( hKeyboardHook );
177.1639 +                KillTimer(hwnd, TIMER_1SEC);
177.1640 +                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
177.1641 +                break;
177.1642 +                default:
177.1643 +//                        pclog("Def %08X %i\n",message,message);
177.1644 +                return DefWindowProc (hwnd, message, wParam, lParam);
177.1645 +        }
177.1646 +        return 0;
177.1647 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/src/win.h	Sun Apr 21 14:54:35 2013 +0100
   178.3 @@ -0,0 +1,3 @@
   178.4 +extern HINSTANCE hinstance;
   178.5 +extern HWND ghwnd;
   178.6 +extern int mousecapture;
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/src/x86.c	Sun Apr 21 14:54:35 2013 +0100
   179.3 @@ -0,0 +1,3686 @@
   179.4 +//1B64 - Vid_SetMode (Vid_Vesa.c)
   179.5 +//6689c - CONS_Printf
   179.6 +/*SHR AX,1
   179.7 +
   179.8 +        4 clocks - fetch opcode
   179.9 +        4 clocks - fetch mod/rm
  179.10 +        2 clocks - execute              2 clocks - fetch opcode 1
  179.11 +                                        2 clocks - fetch opcode 2
  179.12 +                                        4 clocks - fetch mod/rm
  179.13 +        2 clocks - fetch opcode 1       2 clocks - execute
  179.14 +        2 clocks - fetch opcode 2  etc*/
  179.15 +#include <stdio.h>
  179.16 +#include "ibm.h"
  179.17 +#include "x86.h"
  179.18 +#include "mem.h"
  179.19 +#include "keyboard.h"
  179.20 +
  179.21 +int nextcyc=0;
  179.22 +int cycdiff;
  179.23 +int is8086=0;
  179.24 +
  179.25 +int memcycs;
  179.26 +int nopageerrors=0;
  179.27 +float cassettetime;
  179.28 +
  179.29 +void FETCHCOMPLETE();
  179.30 +
  179.31 +uint8_t readmembl(uint32_t addr);
  179.32 +void writemembl(uint32_t addr, uint8_t val);
  179.33 +uint16_t readmemwl(uint32_t seg, uint32_t addr);
  179.34 +void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
  179.35 +uint32_t readmemll(uint32_t seg, uint32_t addr);
  179.36 +void writememll(uint32_t seg, uint32_t addr, uint32_t val);
  179.37 +
  179.38 +#undef readmemb
  179.39 +#undef readmemw
  179.40 +uint8_t readmemb(uint32_t a)
  179.41 +{
  179.42 +        if (a!=(cs+pc)) memcycs+=4;
  179.43 +        if (readlookup2[(a)>>12]==0xFFFFFFFF) return readmembl(a);
  179.44 +        else return ram[readlookup2[(a)>>12]+((a)&0xFFF)];
  179.45 +}
  179.46 +
  179.47 +uint8_t readmembf(uint32_t a)
  179.48 +{
  179.49 +        if (readlookup2[(a)>>12]==0xFFFFFFFF) return readmembl(a);
  179.50 +        else return ram[readlookup2[(a)>>12]+((a)&0xFFF)];
  179.51 +}
  179.52 +
  179.53 +uint16_t readmemw(uint32_t s, uint16_t a)
  179.54 +{
  179.55 +        if (a!=(cs+pc)) memcycs+=(8>>is8086);
  179.56 +        if ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)) return readmemwl(s,a);
  179.57 +        else return *((uint16_t *)(&ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]));
  179.58 +}
  179.59 +
  179.60 +void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; }
  179.61 +
  179.62 +#undef fetchea
  179.63 +#define fetchea()   { rmdat=FETCH();  \
  179.64 +                    reg=(rmdat>>3)&7;             \
  179.65 +                    mod=(rmdat>>6)&3;             \
  179.66 +                    rm=rmdat&7;                   \
  179.67 +                    if (mod!=3) fetcheal(); }
  179.68 +
  179.69 +void writemembl(uint32_t addr, uint8_t val);
  179.70 +void writememb(uint32_t a, uint8_t v)
  179.71 +{
  179.72 +        memcycs+=4;
  179.73 +        if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v);
  179.74 +        else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v;
  179.75 +}
  179.76 +void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
  179.77 +void writememw(uint32_t s, uint32_t a, uint16_t v)
  179.78 +{
  179.79 +        memcycs+=(8>>is8086);
  179.80 +        if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v);
  179.81 +        else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v;
  179.82 +}
  179.83 +void writememll(uint32_t seg, uint32_t addr, uint32_t val);
  179.84 +void writememl(uint32_t s, uint32_t a, uint32_t v)
  179.85 +{
  179.86 +        if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v);
  179.87 +        else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v;
  179.88 +}
  179.89 +
  179.90 +int lldt=0;
  179.91 +int notpresent;
  179.92 +uint16_t oldflags;
  179.93 +void dumpregs();
  179.94 +int incga;
  179.95 +uint32_t old8,old82,old83;
  179.96 +uint16_t oldcs;
  179.97 +int oldcpl;
  179.98 +
  179.99 +int dlE=0;
 179.100 +/*#define CS (cs>>4)
 179.101 +#define DS (ds>>4)
 179.102 +#define ES (es>>4)
 179.103 +#define SS (ss>>4)*/
 179.104 +
 179.105 +//#define loadseg(a) ((a)<<4)
 179.106 +
 179.107 +int keyboardtimer;
 179.108 +int tempc;
 179.109 +int bxcheck=0,spcheck=0;
 179.110 +uint16_t getword();
 179.111 +int count40=0;
 179.112 +int dosfunc;
 179.113 +uint8_t opcode;
 179.114 +int times=0;
 179.115 +uint16_t pc2,pc3;
 179.116 +int pit0=1;
 179.117 +int noint=0;
 179.118 +
 179.119 +int output=0;
 179.120 +
 179.121 +int shadowbios=0;
 179.122 +
 179.123 +int inint=0;
 179.124 +int ins=0;
 179.125 +//#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a))
 179.126 +
 179.127 +int ssegs;
 179.128 +
 179.129 +int fetchcycles=0,memcycs,fetchclocks;
 179.130 +
 179.131 +uint8_t prefetchqueue[6];
 179.132 +uint16_t prefetchpc;
 179.133 +int prefetchw=0;
 179.134 +inline uint8_t FETCH()
 179.135 +{
 179.136 +        uint8_t temp;
 179.137 +/*        temp=prefetchqueue[0];
 179.138 +        prefetchqueue[0]=prefetchqueue[1];
 179.139 +        prefetchqueue[1]=prefetchqueue[2];
 179.140 +        prefetchqueue[2]=prefetchqueue[3];
 179.141 +        prefetchqueue[3]=prefetchqueue[4];
 179.142 +        prefetchqueue[4]=prefetchqueue[5];
 179.143 +        if (prefetchw<=((is8086)?4:3))
 179.144 +        {
 179.145 +                prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
 179.146 +                if (is8086 && (prefetchpc&1))
 179.147 +                {
 179.148 +                        prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
 179.149 +                }
 179.150 +        }*/
 179.151 +
 179.152 +//        uint8_t temp=readmemb(cs+pc);
 179.153 +//        if (output) printf("FETCH %04X %i\n",pc,fetchcycles);
 179.154 +        if (prefetchw==0) //(fetchcycles<4)
 179.155 +        {
 179.156 +                cycles-=(4-(fetchcycles&3));
 179.157 +                fetchclocks+=(4-(fetchcycles&3));
 179.158 +                fetchcycles=4;
 179.159 +                temp=readmembf(cs+pc);
 179.160 +                prefetchpc=pc=pc+1;
 179.161 +//                if (output) printf("   FETCH %04X:%04X %02X %04X %04X %i\n",CS,pc-1,temp,pc,prefetchpc,prefetchw);
 179.162 +                if (is8086 && (pc&1))
 179.163 +                {
 179.164 +                        prefetchqueue[0]=readmembf(cs+pc);
 179.165 +//                        if (output) printf("   PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
 179.166 +                        prefetchpc++;
 179.167 +                        prefetchw++;
 179.168 +                }
 179.169 +        }
 179.170 +        else
 179.171 +        {
 179.172 +                temp=prefetchqueue[0];
 179.173 +                prefetchqueue[0]=prefetchqueue[1];
 179.174 +                prefetchqueue[1]=prefetchqueue[2];
 179.175 +                prefetchqueue[2]=prefetchqueue[3];
 179.176 +                prefetchqueue[3]=prefetchqueue[4];
 179.177 +                prefetchqueue[4]=prefetchqueue[5];
 179.178 +                prefetchw--;
 179.179 +//                if (output) printf("PREFETCH %04X:%04X %02X %04X %04X %i\n",CS,pc,temp,pc,prefetchpc,prefetchw);
 179.180 +                fetchcycles-=4;
 179.181 +//                fetchclocks+=4;
 179.182 +                pc++;
 179.183 +        }
 179.184 +//        if (output) printf("%i\n",fetchcycles);
 179.185 +        return temp;
 179.186 +}
 179.187 +
 179.188 +inline void FETCHADD(int c)
 179.189 +{
 179.190 +        int d;
 179.191 +//        if (output) printf("FETCHADD %i\n",c);
 179.192 +        if (c<0) return;
 179.193 +        if (prefetchw>((is8086)?4:3)) return;
 179.194 +        d=c+(fetchcycles&3);
 179.195 +        while (d>3 && prefetchw<((is8086)?6:4))
 179.196 +        {
 179.197 +                d-=4;
 179.198 +                if (is8086 && !(prefetchpc&1))
 179.199 +                {
 179.200 +                        prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
 179.201 +//                        printf("PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
 179.202 +                        prefetchpc++;
 179.203 +                        prefetchw++;
 179.204 +                }
 179.205 +                if (prefetchw<6)
 179.206 +                {
 179.207 +                        prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
 179.208 +//                        printf("PREFETCHED from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
 179.209 +                        prefetchpc++;
 179.210 +                        prefetchw++;
 179.211 +                }
 179.212 +        }
 179.213 +        fetchcycles+=c;
 179.214 +        if (fetchcycles>16) fetchcycles=16;
 179.215 +//        if (fetchcycles>24) fetchcycles=24;
 179.216 +}
 179.217 +
 179.218 +void FETCHCOMPLETE()
 179.219 +{
 179.220 +//        pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw);
 179.221 +        if (!(fetchcycles&3)) return;
 179.222 +        if (prefetchw>((is8086)?4:3)) return;
 179.223 +        if (!prefetchw) nextcyc=(4-(fetchcycles&3));
 179.224 +        cycles-=(4-(fetchcycles&3));
 179.225 +        fetchclocks+=(4-(fetchcycles&3));
 179.226 +                if (is8086 && !(prefetchpc&1))
 179.227 +                {
 179.228 +                        prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
 179.229 +//                        printf("PREFETCHEDc from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
 179.230 +                        prefetchpc++;
 179.231 +                        prefetchw++;
 179.232 +                }
 179.233 +                if (prefetchw<6)
 179.234 +                {
 179.235 +                        prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
 179.236 +//                        printf("PREFETCHEDc from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
 179.237 +                        prefetchpc++;
 179.238 +                        prefetchw++;
 179.239 +                }
 179.240 +                fetchcycles+=(4-(fetchcycles&3));
 179.241 +}
 179.242 +
 179.243 +inline void FETCHCLEAR()
 179.244 +{
 179.245 +/*        int c;
 179.246 +        fetchcycles=0;
 179.247 +        prefetchpc=pc;
 179.248 +        if (is8086 && (prefetchpc&1)) cycles-=4;
 179.249 +        for (c=0;c<((is8086)?6:4);c++)
 179.250 +        {
 179.251 +                prefetchqueue[c]=readmembf(cs+prefetchpc);
 179.252 +                if (!is8086 || !(prefetchpc&1)) cycles-=4;
 179.253 +                prefetchpc++;
 179.254 +        }
 179.255 +        prefetchw=(is8086)?6:4;*/
 179.256 +//        fetchcycles=0;
 179.257 +        prefetchpc=pc;
 179.258 +        prefetchw=0;
 179.259 +        memcycs=cycdiff-cycles;
 179.260 +        fetchclocks=0;
 179.261 +//        memcycs=cycles;
 179.262 +/*        prefetchqueue[0]=readmembf(cs+prefetchpc);
 179.263 +        prefetchpc++;
 179.264 +        prefetchw=1;
 179.265 +        if (is8086 && prefetchpc&1)
 179.266 +        {
 179.267 +                prefetchqueue[1]=readmembf(cs+prefetchpc);
 179.268 +                prefetchpc++;
 179.269 +        }*/
 179.270 +}
 179.271 +
 179.272 +/*EA calculation*/
 179.273 +
 179.274 +/*R/M - bits 0-2 - R/M   bits 3-5 - Reg   bits 6-7 - mod
 179.275 +  From 386 programmers manual :
 179.276 +r8(/r)                     AL    CL    DL    BL    AH    CH    DH    BH
 179.277 +r16(/r)                    AX    CX    DX    BX    SP    BP    SI    DI
 179.278 +r32(/r)                    EAX   ECX   EDX   EBX   ESP   EBP   ESI   EDI
 179.279 +/digit (Opcode)            0     1     2     3     4     5     6     7
 179.280 +REG =                      000   001   010   011   100   101   110   111
 179.281 +  ÚÄÄÄAddress
 179.282 +disp8 denotes an 8-bit displacement following the ModR/M byte, to be
 179.283 +sign-extended and added to the index. disp16 denotes a 16-bit displacement
 179.284 +following the ModR/M byte, to be added to the index. Default segment
 179.285 +register is SS for the effective addresses containing a BP index, DS for
 179.286 +other effective addresses.
 179.287 +            ÄÄ¿ ÚMod R/M¿ ÚÄÄÄÄÄÄÄÄModR/M Values in HexadecimalÄÄÄÄÄÄÄÄ¿
 179.288 +
 179.289 +[BX + SI]            000   00    08    10    18    20    28    30    38
 179.290 +[BX + DI]            001   01    09    11    19    21    29    31    39
 179.291 +[BP + SI]            010   02    0A    12    1A    22    2A    32    3A
 179.292 +[BP + DI]            011   03    0B    13    1B    23    2B    33    3B
 179.293 +[SI]             00  100   04    0C    14    1C    24    2C    34    3C
 179.294 +[DI]                 101   05    0D    15    1D    25    2D    35    3D
 179.295 +disp16               110   06    0E    16    1E    26    2E    36    3E
 179.296 +[BX]                 111   07    0F    17    1F    27    2F    37    3F
 179.297 +
 179.298 +[BX+SI]+disp8        000   40    48    50    58    60    68    70    78
 179.299 +[BX+DI]+disp8        001   41    49    51    59    61    69    71    79
 179.300 +[BP+SI]+disp8        010   42    4A    52    5A    62    6A    72    7A
 179.301 +[BP+DI]+disp8        011   43    4B    53    5B    63    6B    73    7B
 179.302 +[SI]+disp8       01  100   44    4C    54    5C    64    6C    74    7C
 179.303 +[DI]+disp8           101   45    4D    55    5D    65    6D    75    7D
 179.304 +[BP]+disp8           110   46    4E    56    5E    66    6E    76    7E
 179.305 +[BX]+disp8           111   47    4F    57    5F    67    6F    77    7F
 179.306 +
 179.307 +[BX+SI]+disp16       000   80    88    90    98    A0    A8    B0    B8
 179.308 +[BX+DI]+disp16       001   81    89    91    99    A1    A9    B1    B9
 179.309 +[BX+SI]+disp16       010   82    8A    92    9A    A2    AA    B2    BA
 179.310 +[BX+DI]+disp16       011   83    8B    93    9B    A3    AB    B3    BB
 179.311 +[SI]+disp16      10  100   84    8C    94    9C    A4    AC    B4    BC
 179.312 +[DI]+disp16          101   85    8D    95    9D    A5    AD    B5    BD
 179.313 +[BP]+disp16          110   86    8E    96    9E    A6    AE    B6    BE
 179.314 +[BX]+disp16          111   87    8F    97    9F    A7    AF    B7    BF
 179.315 +
 179.316 +EAX/AX/AL            000   C0    C8    D0    D8    E0    E8    F0    F8
 179.317 +ECX/CX/CL            001   C1    C9    D1    D9    E1    E9    F1    F9
 179.318 +EDX/DX/DL            010   C2    CA    D2    DA    E2    EA    F2    FA
 179.319 +EBX/BX/BL            011   C3    CB    D3    DB    E3    EB    F3    FB
 179.320 +ESP/SP/AH        11  100   C4    CC    D4    DC    E4    EC    F4    FC
 179.321 +EBP/BP/CH            101   C5    CD    D5    DD    E5    ED    F5    FD
 179.322 +ESI/SI/DH            110   C6    CE    D6    DE    E6    EE    F6    FE
 179.323 +EDI/DI/BH            111   C7    CF    D7    DF    E7    EF    F7    FF
 179.324 +
 179.325 +mod = 11 - register
 179.326 +      10 - address + 16 bit displacement
 179.327 +      01 - address + 8 bit displacement
 179.328 +      00 - address
 179.329 +
 179.330 +reg = If mod=11,  (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers)
 179.331 +      0=AX/AL   1=CX/CL   2=DX/DL   3=BX/BL
 179.332 +      4=SP/AH   5=BP/CH   6=SI/DH   7=DI/BH
 179.333 +
 179.334 +      Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB
 179.335 +      selects whether BX/BP are used at all (0=used).
 179.336 +
 179.337 +      mod=00 is an exception though
 179.338 +      6=16 bit displacement only
 179.339 +      7=[BX]
 179.340 +
 179.341 +      Usage varies with instructions.
 179.342 +
 179.343 +      MOV AL,BL has ModR/M as C3, for example.
 179.344 +      mod=11, reg=0, r/m=3
 179.345 +      MOV uses reg as dest, and r/m as src.
 179.346 +      reg 0 is AL, reg 3 is BL
 179.347 +
 179.348 +      If BP or SP are in address calc, seg is SS, else DS
 179.349 +*/
 179.350 +
 179.351 +int cycles=0;
 179.352 +uint32_t easeg,eaaddr;
 179.353 +int rm,reg,mod,rmdat;
 179.354 +
 179.355 +uint16_t zero=0;
 179.356 +uint16_t *mod1add[2][8];
 179.357 +uint32_t *mod1seg[8];
 179.358 +
 179.359 +int slowrm[8];
 179.360 +
 179.361 +void makemod1table()
 179.362 +{
 179.363 +        mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP;
 179.364 +        mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX;
 179.365 +        mod1add[1][0]=&SI; mod1add[1][1]=&DI; mod1add[1][2]=&SI; mod1add[1][3]=&DI;
 179.366 +        mod1add[1][4]=&zero; mod1add[1][5]=&zero; mod1add[1][6]=&zero; mod1add[1][7]=&zero;
 179.367 +        slowrm[0]=0; slowrm[1]=1; slowrm[2]=1; slowrm[3]=0;
 179.368 +        mod1seg[0]=&ds; mod1seg[1]=&ds; mod1seg[2]=&ss; mod1seg[3]=&ss;
 179.369 +        mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds;
 179.370 +}
 179.371 +
 179.372 +void fetcheal()
 179.373 +{
 179.374 +        if (!mod && rm==6) { eaaddr=getword(); easeg=ds; FETCHADD(6); }
 179.375 +        else
 179.376 +        {
 179.377 +                switch (mod)
 179.378 +                {
 179.379 +                        case 0:
 179.380 +                        eaaddr=0;
 179.381 +                        if (rm&4) FETCHADD(5);
 179.382 +                        else      FETCHADD(7+slowrm[rm]);
 179.383 +                        break;
 179.384 +                        case 1:
 179.385 +                        eaaddr=(uint16_t)(int8_t)FETCH();
 179.386 +                        if (rm&4) FETCHADD(9);
 179.387 +                        else      FETCHADD(11+slowrm[rm]);
 179.388 +                        break;
 179.389 +                        case 2:
 179.390 +                        eaaddr=getword();
 179.391 +                        if (rm&4) FETCHADD(9);
 179.392 +                        else      FETCHADD(11+slowrm[rm]);
 179.393 +                        break;
 179.394 +                }
 179.395 +                eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]);
 179.396 +                easeg=*mod1seg[rm];
 179.397 +                eaaddr&=0xFFFF;
 179.398 +        }
 179.399 +}
 179.400 +
 179.401 +/*void fetchea()
 179.402 +{
 179.403 +        rmdat=readmemb(cs+pc); pc++;
 179.404 +        reg=(rmdat>>3)&7;
 179.405 +        mod=rmdat>>6;
 179.406 +        rm=rmdat&7;
 179.407 +        switch (mod)
 179.408 +        {
 179.409 +                case 0:
 179.410 +                switch (rm)
 179.411 +                {
 179.412 +                        case 0: eaaddr=BX+SI; easeg=ds; if (!AT) cycles-=7; break;
 179.413 +                        case 1: eaaddr=BX+DI; easeg=ds; if (!AT) cycles-=8; break;
 179.414 +                        case 2: eaaddr=BP+SI; easeg=ss; if (!AT) cycles-=8; break;
 179.415 +                        case 3: eaaddr=BP+DI; easeg=ss; if (!AT) cycles-=7; break;
 179.416 +                        case 4: eaaddr=SI; easeg=ds; if (!AT) cycles-=5; break;
 179.417 +                        case 5: eaaddr=DI; easeg=ds; if (!AT) cycles-=5; break;
 179.418 +                        case 6: eaaddr=getword(); easeg=ds; if (!AT) cycles-=6; break;
 179.419 +                        case 7: eaaddr=BX; easeg=ds; if (!AT) cycles-=5; break;
 179.420 +                }
 179.421 +                if (AT && !(rm&4)) cycles--;
 179.422 +                break;
 179.423 +
 179.424 +                case 1:
 179.425 +                eaaddr=readmemb(cs+pc); pc++;
 179.426 +                if (eaaddr&0x80) eaaddr|=0xFF00;
 179.427 +//                if (output) printf("EAADDR %04X ",eaaddr);
 179.428 +                switch (rm)
 179.429 +                {
 179.430 +                        case 0: eaaddr+=BX+SI; easeg=ds; if (!AT) cycles-=11; break;
 179.431 +                        case 1: eaaddr+=BX+DI; easeg=ds; if (!AT) cycles-=12; break;
 179.432 +                        case 2: eaaddr+=BP+SI; easeg=ss; if (!AT) cycles-=12; break;
 179.433 +                        case 3: eaaddr+=BP+DI; easeg=ss; if (!AT) cycles-=11; break;
 179.434 +                        case 4: eaaddr+=SI; easeg=ds; if (!AT) cycles-=9; break;
 179.435 +                        case 5: eaaddr+=DI; easeg=ds; if (!AT) cycles-=9; break;
 179.436 +                        case 6: eaaddr+=BP; easeg=ss; if (!AT) cycles-=9; break;
 179.437 +                        case 7: eaaddr+=BX; easeg=ds; if (!AT) cycles-=9; break;
 179.438 +                }
 179.439 +                if (AT && !(rm&4)) cycles--;
 179.440 +//                if (output) printf("%04X %04X",eaaddr,BX);
 179.441 +                break;
 179.442 +
 179.443 +                case 2:
 179.444 +                eaaddr=getword();
 179.445 +                switch (rm)
 179.446 +                {
 179.447 +                        case 0: eaaddr+=BX+SI; easeg=ds; if (!AT) cycles-=11; break;
 179.448 +                        case 1: eaaddr+=BX+DI; easeg=ds; if (!AT) cycles-=12; break;
 179.449 +                        case 2: eaaddr+=BP+SI; easeg=ss; if (!AT) cycles-=12; break;
 179.450 +                        case 3: eaaddr+=BP+DI; easeg=ss; if (!AT) cycles-=11; break;
 179.451 +                        case 4: eaaddr+=SI; easeg=ds; if (!AT) cycles-=9; break;
 179.452 +                        case 5: eaaddr+=DI; easeg=ds; if (!AT) cycles-=9; break;
 179.453 +                        case 6: eaaddr+=BP; easeg=ss; if (!AT) cycles-=9; break;
 179.454 +                        case 7: eaaddr+=BX; easeg=ds; if (!AT) cycles-=9; break;
 179.455 +                }
 179.456 +                if (AT && !(rm&4)) cycles--;
 179.457 +                break;
 179.458 +        }
 179.459 +        eaaddr&=0xFFFF;
 179.460 +}*/
 179.461 +
 179.462 +static inline uint8_t geteab()
 179.463 +{
 179.464 +        if (mod==3)
 179.465 +           return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
 179.466 +        return readmemb(easeg+eaaddr);
 179.467 +}
 179.468 +
 179.469 +static inline uint16_t geteaw()
 179.470 +{
 179.471 +        if (mod==3)
 179.472 +           return regs[rm].w;
 179.473 +//        if (output==3) printf("GETEAW %04X:%08X\n",easeg,eaaddr);
 179.474 +        return readmemw(easeg,eaaddr);
 179.475 +}
 179.476 +
 179.477 +static inline uint16_t geteaw2()
 179.478 +{
 179.479 +        if (mod==3)
 179.480 +           return regs[rm].w;
 179.481 +//        printf("Getting addr from %04X:%04X %05X\n",easeg,eaaddr+2,easeg+eaaddr+2);
 179.482 +        return readmemw(easeg,(eaaddr+2)&0xFFFF);
 179.483 +}
 179.484 +
 179.485 +static inline void seteab(uint8_t val)
 179.486 +{
 179.487 +        if (mod==3)
 179.488 +        {
 179.489 +                if (rm&4) regs[rm&3].b.h=val;
 179.490 +                else      regs[rm&3].b.l=val;
 179.491 +        }
 179.492 +        else
 179.493 +        {
 179.494 +                writememb(easeg+eaaddr,val);
 179.495 +        }
 179.496 +}
 179.497 +
 179.498 +static inline void seteaw(uint16_t val)
 179.499 +{
 179.500 +        if (mod==3)
 179.501 +           regs[rm].w=val;
 179.502 +        else
 179.503 +        {
 179.504 +                writememw(easeg,eaaddr,val);
 179.505 +//                writememb(easeg+eaaddr+1,val>>8);
 179.506 +        }
 179.507 +}
 179.508 +
 179.509 +#define getr8(r)   ((r&4)?regs[r&3].b.h:regs[r&3].b.l)
 179.510 +
 179.511 +#define setr8(r,v) if (r&4) regs[r&3].b.h=v; \
 179.512 +                   else     regs[r&3].b.l=v;
 179.513 +
 179.514 +
 179.515 +/*Flags*/
 179.516 +uint8_t znptable8[256];
 179.517 +uint16_t znptable16[65536];
 179.518 +
 179.519 +void makeznptable()
 179.520 +{
 179.521 +        int c,d;
 179.522 +        for (c=0;c<256;c++)
 179.523 +        {
 179.524 +                d=0;
 179.525 +                if (c&1) d++;
 179.526 +                if (c&2) d++;
 179.527 +                if (c&4) d++;
 179.528 +                if (c&8) d++;
 179.529 +                if (c&16) d++;
 179.530 +                if (c&32) d++;
 179.531 +                if (c&64) d++;
 179.532 +                if (c&128) d++;
 179.533 +                if (d&1)
 179.534 +                   znptable8[c]=0;
 179.535 +                else
 179.536 +                   znptable8[c]=P_FLAG;
 179.537 +                   if (c == 0xb1) pclog("znp8 b1 = %i %02X\n", d, znptable8[c]);
 179.538 +                if (!c) znptable8[c]|=Z_FLAG;
 179.539 +                if (c&0x80) znptable8[c]|=N_FLAG;
 179.540 +        }
 179.541 +        for (c=0;c<65536;c++)
 179.542 +        {
 179.543 +                d=0;
 179.544 +                if (c&1) d++;
 179.545 +                if (c&2) d++;
 179.546 +                if (c&4) d++;
 179.547 +                if (c&8) d++;
 179.548 +                if (c&16) d++;
 179.549 +                if (c&32) d++;
 179.550 +                if (c&64) d++;
 179.551 +                if (c&128) d++;
 179.552 +                if (d&1)
 179.553 +                   znptable16[c]=0;
 179.554 +                else
 179.555 +                   znptable16[c]=P_FLAG;
 179.556 +                if (c == 0xb1) pclog("znp16 b1 = %i %02X\n", d, znptable16[c]);
 179.557 +                if (c == 0x65b1) pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]);
 179.558 +                if (!c) znptable16[c]|=Z_FLAG;
 179.559 +                if (c&0x8000) znptable16[c]|=N_FLAG;
 179.560 +      }
 179.561 +//        isram[0xF]=1;
 179.562 +//        printf("isram 0 = %i\n",isram[0]);
 179.563 +      
 179.564 +//      makemod1table();
 179.565 +}
 179.566 +int timetolive=0;
 179.567 +
 179.568 +uint8_t cpu_readop(uint32_t addr) { return readmemb(addr); }
 179.569 +uint8_t cpu_readmem20(uint32_t addr) { return readmemb(addr); }
 179.570 +
 179.571 +void cpu_writemem20(uint32_t addr, uint8_t val) { writememb(addr,val); }
 179.572 +
 179.573 +uint16_t getword()
 179.574 +{
 179.575 +        uint8_t temp=FETCH();
 179.576 +        return temp|(FETCH()<<8);
 179.577 +//        pc+=2;
 179.578 +//        return readmemw(cs,(pc-2));
 179.579 +}
 179.580 +
 179.581 +uint16_t getword286()
 179.582 +{
 179.583 +        uint16_t temp=readmemw(cs,pc); pc+=2;
 179.584 +        return temp;
 179.585 +}
 179.586 +
 179.587 +int ratio1=0,ratio2=0;
 179.588 +
 179.589 +extern uint32_t oldcs2;
 179.590 +extern uint32_t oldpc2;
 179.591 +
 179.592 +void dumpregs()
 179.593 +{
 179.594 +        FILE *f;
 179.595 +        int c,d=0,e=0;
 179.596 +//        return;
 179.597 +        output=0;
 179.598 +//        return;
 179.599 +//        savenvr();
 179.600 +/*        printf("The ratio is %i %i\n",ratio1,ratio2);
 179.601 +        for (c=0;c<256;c++)
 179.602 +        {
 179.603 +                printf("ISRAM : %06X %i\n",c<<16,isram[c]);
 179.604 +        }*/
 179.605 +//        return;
 179.606 +chdir(pcempath);
 179.607 +        nopageerrors=1;
 179.608 +/*        f=fopen("rram3.dmp","wb");
 179.609 +        for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f);
 179.610 +        fclose(f);*/
 179.611 +/*        f=fopen("ram.dmp","wb");
 179.612 +        fwrite(ram,mem_size*1024*1024,1,f);
 179.613 +        fclose(f);*/
 179.614 +/*        f=fopen("rram.dmp","wb");
 179.615 +        for (c=0;c<0x1000000;c++) putc(readmemb(c),f);
 179.616 +        fclose(f);
 179.617 +        f=fopen("rram2.dmp","wb");
 179.618 +        for (c=0;c<0x100000;c++) putc(readmemb(c+0xbff00000),f);
 179.619 +        fclose(f);
 179.620 +        f = fopen("stack.dmp","wb");
 179.621 +        for (c = 0; c < 0x6000; c++) putc(readmemb(c+0xFFDFA000), f);
 179.622 +        fclose(f);
 179.623 +        f = fopen("tempx.dmp","wb");
 179.624 +        for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFC816000), f);
 179.625 +        fclose(f);
 179.626 +        f = fopen("tempx2.dmp","wb");
 179.627 +        for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFDEF5000), f);
 179.628 +        fclose(f);*/
 179.629 +/*        f=fopen("rram4.dmp","wb");
 179.630 +        for (c=0;c<0x3000000;c++) putc(readmemb(c+0x80000000),f);
 179.631 +        fclose(f);*/
 179.632 +/*        f=fopen("rram5.dmp","wb");
 179.633 +        for (c=0;c<0x1000000;c++) putc(readmemb(c+0x10000000),f);
 179.634 +        fclose(f);*/
 179.635 +/*        f=fopen("rram6.dmp","wb");
 179.636 +        for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f);
 179.637 +        fclose(f);*/
 179.638 +/*        f=fopen("ram6.bin","wb");
 179.639 +        fwrite(ram+0x10100,0xA000,1,f);
 179.640 +        fclose(f);
 179.641 +        f=fopen("boot.bin","wb");
 179.642 +        fwrite(ram+0x7C00,0x200,1,f);
 179.643 +        fclose(f);
 179.644 +        f=fopen("ram7.bin","wb");
 179.645 +        fwrite(ram+0x11100,0x2000,1,f);
 179.646 +        fclose(f);
 179.647 +        f=fopen("ram8.bin","wb");
 179.648 +        fwrite(ram+0x3D210,0x200,1,f);
 179.649 +        fclose(f);        */
 179.650 +/*        f=fopen("vram.dmp","wb");
 179.651 +        fwrite(vram,0x400000,1,f);
 179.652 +        fclose(f);
 179.653 +        f=fopen("bios.dmp","wb");
 179.654 +        fwrite(rom,0x20000,1,f);
 179.655 +        fclose(f);
 179.656 +        f=fopen("vbios.dmp","wb");
 179.657 +        fwrite(vrom,0x8000,1,f);
 179.658 +        fclose(f);*/
 179.659 +/*        f=fopen("kernel.dmp","wb");
 179.660 +        for (c=0;c<0x200000;c++) putc(readmemb(c+0xC0000000),f);
 179.661 +        fclose(f);*/
 179.662 +/*        f=fopen("rram.dmp","wb");
 179.663 +        for (c=0;c<0x1500000;c++) putc(readmemb(c),f);
 179.664 +        fclose(f);
 179.665 +        if (!times)
 179.666 +        {
 179.667 +                f=fopen("thing.dmp","wb");
 179.668 +                fwrite(ram+0x11E50,0x1000,1,f);
 179.669 +                fclose(f);
 179.670 +        }*/
 179.671 +        if (is386)
 179.672 +           printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP);
 179.673 +        else
 179.674 +           printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP);
 179.675 +        printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",pc,CS,DS,ES,SS,flags);
 179.676 +        printf("%04X:%04X %04X:%04X %08X %08X %08X\n",oldcs,oldpc, oldcs2, oldpc2, old8,old82,old83);
 179.677 +        printf("%i ins\n",ins);
 179.678 +        if (is386)
 179.679 +           printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real");
 179.680 +        else
 179.681 +           printf("In %s mode\n",(msw&1)?"protected":"real");
 179.682 +        printf("CS : base=%06X limit=%04X access=%02X\n",cs,_cs.limit,_cs.access);
 179.683 +        printf("DS : base=%06X limit=%04X access=%02X\n",ds,_ds.limit,_ds.access);
 179.684 +        printf("ES : base=%06X limit=%04X access=%02X\n",es,_es.limit,_es.access);
 179.685 +        if (is386)
 179.686 +        {
 179.687 +                printf("FS : base=%06X limit=%04X access=%02X\n",fs,_fs.limit,_fs.access);
 179.688 +                printf("GS : base=%06X limit=%04X access=%02X\n",gs,_gs.limit,_gs.access);
 179.689 +        }
 179.690 +        printf("SS : base=%06X limit=%04X access=%02X\n",ss,_ss.limit,_ss.access);
 179.691 +        printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit);
 179.692 +        printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit);
 179.693 +        printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit);
 179.694 +        printf("TR  : base=%06X limit=%04X\n", tr.base, tr.limit);
 179.695 +        if (is386)
 179.696 +        {
 179.697 +                printf("386 in %s mode   stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
 179.698 +                printf("CR0=%08X CR2=%08X CR3=%08X\n",cr0,cr2,cr3);
 179.699 +        }
 179.700 +        printf("Entries in readlookup : %i    writelookup : %i\n",readlnum,writelnum);
 179.701 +        for (c=0;c<1024*1024;c++)
 179.702 +        {
 179.703 +                if (readlookup2[c]!=0xFFFFFFFF) d++;
 179.704 +                if (writelookup2[c]!=0xFFFFFFFF) e++;
 179.705 +        }
 179.706 +        printf("Entries in readlookup : %i    writelookup : %i\n",d,e);
 179.707 +        d=0;
 179.708 +        x87_dumpregs();
 179.709 +/*        for (c=0;c<1024*1024;c++)
 179.710 +        {
 179.711 +                if (mmucache[c]!=0xFFFFFFFF) d++;
 179.712 +        }
 179.713 +        printf("Entries in MMU cache : %i\n",d);*/
 179.714 +}
 179.715 +
 179.716 +int isAT;
 179.717 +int resets = 0;
 179.718 +void resetx86()
 179.719 +{
 179.720 +        pclog("x86 reset\n");
 179.721 +        resets++;
 179.722 +        ins = 0;
 179.723 +        use32=0;
 179.724 +        stack32=0;
 179.725 +//        i86_Reset();
 179.726 +//        cs=0xFFFF0;
 179.727 +        pc=0;
 179.728 +        msw=0;
 179.729 +        cr0=0;
 179.730 +        eflags=0;
 179.731 +        cgate32=0;
 179.732 +        loadcs(0xFFFF);
 179.733 +        rammask=0xFFFFFFFF;
 179.734 +        flags=2;
 179.735 +        initmmucache();
 179.736 +        resetreadlookup();
 179.737 +        makemod1table();
 179.738 +        resetmcr();
 179.739 +        isAT=AT;
 179.740 +        FETCHCLEAR();
 179.741 +        x87_reset();
 179.742 +        cpu_set_edx();
 179.743 +        ESP=0;
 179.744 +        mmu_perm=4;
 179.745 +}
 179.746 +
 179.747 +void softresetx86()
 179.748 +{
 179.749 +//      dumpregs();
 179.750 +//        exit(-1);
 179.751 +        use32=0;
 179.752 +        stack32=0;
 179.753 +//        i86_Reset();
 179.754 +//        cs=0xFFFF0;
 179.755 +        pc=0;
 179.756 +        msw=0;
 179.757 +        cr0=0;
 179.758 +        eflags=0;
 179.759 +        cgate32=0;
 179.760 +        loadcs(0xFFFF);
 179.761 +        //rammask=0xFFFFFFFF;
 179.762 +        flags=2;
 179.763 +}
 179.764 +
 179.765 +#undef AT
 179.766 +#define AT isAT
 179.767 +
 179.768 +extern int is486;
 179.769 +void setznp8(uint8_t val)
 179.770 +{
 179.771 +        flags&=~0xC4;
 179.772 +        flags|=znptable8[val];
 179.773 +}
 179.774 +
 179.775 +#define setznp168 setznp16
 179.776 +void setznp16(uint16_t val)
 179.777 +{
 179.778 +        flags&=~0xC4;
 179.779 +//        flags|=((val&0x8000)?N_FLAG:((!val)?Z_FLAG:0));
 179.780 +//        flags|=(((znptable8[val&0xFF]&P_FLAG)==(znptable8[val>>8]&P_FLAG))?P_FLAG:0);
 179.781 +        flags|=znptable16[val];
 179.782 +}
 179.783 +
 179.784 +/*void setznp168(uint16_t val)
 179.785 +{
 179.786 +        flags&=~0xC4;
 179.787 +        flags|=(znptable16[val]&0xC0)|(znptable8[val&0xFF]&4);
 179.788 +}*/
 179.789 +
 179.790 +void setadd8(uint8_t a, uint8_t b)
 179.791 +{
 179.792 +        uint16_t c=(uint16_t)a+(uint16_t)b;
 179.793 +        flags&=~0x8D5;
 179.794 +        flags|=znptable8[c&0xFF];
 179.795 +        if (c&0x100) flags|=C_FLAG;
 179.796 +        if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
 179.797 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.798 +}
 179.799 +void setadd8nc(uint8_t a, uint8_t b)
 179.800 +{
 179.801 +        uint16_t c=(uint16_t)a+(uint16_t)b;
 179.802 +        flags&=~0x8D4;
 179.803 +        flags|=znptable8[c&0xFF];
 179.804 +        if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
 179.805 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.806 +}
 179.807 +void setadc8(uint8_t a, uint8_t b)
 179.808 +{
 179.809 +        uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
 179.810 +        flags&=~0x8D5;
 179.811 +        flags|=znptable8[c&0xFF];
 179.812 +        if (c&0x100) flags|=C_FLAG;
 179.813 +        if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
 179.814 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.815 +}
 179.816 +void setadd16(uint16_t a, uint16_t b)
 179.817 +{
 179.818 +        uint32_t c=(uint32_t)a+(uint32_t)b;
 179.819 +        flags&=~0x8D5;
 179.820 +        flags|=znptable16[c&0xFFFF];
 179.821 +        if (c&0x10000) flags|=C_FLAG;
 179.822 +        if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
 179.823 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.824 +}
 179.825 +void setadd16nc(uint16_t a, uint16_t b)
 179.826 +{
 179.827 +        uint32_t c=(uint32_t)a+(uint32_t)b;
 179.828 +        flags&=~0x8D4;
 179.829 +        flags|=znptable16[c&0xFFFF];
 179.830 +        if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
 179.831 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.832 +}
 179.833 +void setadc16(uint16_t a, uint16_t b)
 179.834 +{
 179.835 +        uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
 179.836 +        flags&=~0x8D5;
 179.837 +        flags|=znptable16[c&0xFFFF];
 179.838 +        if (c&0x10000) flags|=C_FLAG;
 179.839 +        if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
 179.840 +        if (((a&0xF)+(b&0xF))&0x10)      flags|=A_FLAG;
 179.841 +}
 179.842 +
 179.843 +void setsub8(uint8_t a, uint8_t b)
 179.844 +{
 179.845 +        uint16_t c=(uint16_t)a-(uint16_t)b;
 179.846 +        flags&=~0x8D5;
 179.847 +        flags|=znptable8[c&0xFF];
 179.848 +        if (c&0x100) flags|=C_FLAG;
 179.849 +        if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
 179.850 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.851 +}
 179.852 +void setsub8nc(uint8_t a, uint8_t b)
 179.853 +{
 179.854 +        uint16_t c=(uint16_t)a-(uint16_t)b;
 179.855 +        flags&=~0x8D4;
 179.856 +        flags|=znptable8[c&0xFF];
 179.857 +        if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
 179.858 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.859 +}
 179.860 +void setsbc8(uint8_t a, uint8_t b)
 179.861 +{
 179.862 +        uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
 179.863 +        flags&=~0x8D5;
 179.864 +        flags|=znptable8[c&0xFF];
 179.865 +        if (c&0x100) flags|=C_FLAG;
 179.866 +        if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
 179.867 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.868 +}
 179.869 +void setsub16(uint16_t a, uint16_t b)
 179.870 +{
 179.871 +        uint32_t c=(uint32_t)a-(uint32_t)b;
 179.872 +        flags&=~0x8D5;
 179.873 +        flags|=znptable16[c&0xFFFF];
 179.874 +        if (c&0x10000) flags|=C_FLAG;
 179.875 +        if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
 179.876 +//        if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG);
 179.877 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.878 +}
 179.879 +void setsub16nc(uint16_t a, uint16_t b)
 179.880 +{
 179.881 +        uint32_t c=(uint32_t)a-(uint32_t)b;
 179.882 +        flags&=~0x8D4;
 179.883 +        flags|=(znptable16[c&0xFFFF]&~4);
 179.884 +        flags|=(znptable8[c&0xFF]&4);
 179.885 +        if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
 179.886 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.887 +}
 179.888 +void setsbc16(uint16_t a, uint16_t b)
 179.889 +{
 179.890 +        uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
 179.891 +        flags&=~0x8D5;
 179.892 +        flags|=(znptable16[c&0xFFFF]&~4);
 179.893 +        flags|=(znptable8[c&0xFF]&4);
 179.894 +        if (c&0x10000) flags|=C_FLAG;
 179.895 +        if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
 179.896 +        if (((a&0xF)-(b&0xF))&0x10)      flags|=A_FLAG;
 179.897 +}
 179.898 +
 179.899 +
 179.900 +void clockhardware()
 179.901 +{
 179.902 +                cycdiff-=cycles;
 179.903 +                
 179.904 +                keybsenddelay--;
 179.905 +                if (keybsenddelay<1)
 179.906 +                {
 179.907 +                        keybsenddelay = 1000;//2500;
 179.908 +                        keyboard_poll();
 179.909 +                }
 179.910 +
 179.911 +                pit.c[0]-=cycdiff;
 179.912 +                pit.c[1]-=cycdiff;
 179.913 +                if (ppi.pb&1) pit.c[2]-=cycdiff;
 179.914 +
 179.915 +                if ((pit.c[0]<1)||(pit.c[1]<1)||(pit.c[2]<1)) pit_poll();
 179.916 +
 179.917 +                spktime-=cycdiff;
 179.918 +                if (spktime<=0.0)
 179.919 +                {
 179.920 +                        spktime+=SPKCONST;
 179.921 +                        pollspk();
 179.922 +                        pollgussamp();
 179.923 +                        getsbsamp();
 179.924 +                        getdacsamp();
 179.925 +                        polladlib();
 179.926 +                }
 179.927 +                soundtime-=cycdiff;
 179.928 +                if (soundtime<=0.0)
 179.929 +                {
 179.930 +                        soundtime+=SOUNDCONST;
 179.931 +                        pollsound60hz();
 179.932 +                }
 179.933 +                gustime-=cycdiff;
 179.934 +                while (gustime<=0.0)
 179.935 +                {
 179.936 +                        gustime+=GUSCONST;
 179.937 +//                        printf("1Poll GUS %f %f\n",gustime,GUSCONST);
 179.938 +                        pollgus();
 179.939 +//                        printf("2Poll GUS\n");
 179.940 +                }
 179.941 +                vidtime-=cycdiff;
 179.942 +                if (vidtime<=0.0)
 179.943 +                {
 179.944 +                        pollvideo();
 179.945 +//                        polltandy();
 179.946 +//                        pollmda();
 179.947 +//                        pollcga();
 179.948 +                }
 179.949 +                if (disctime)
 179.950 +                {
 179.951 +                        disctime-=(cycdiff/2);
 179.952 +                        if (disctime<=0)
 179.953 +                        {
 179.954 +                                disctime=0;
 179.955 +                                fdc_poll();
 179.956 +                        }
 179.957 +                }
 179.958 +                if (mousedelay)
 179.959 +                {
 179.960 +                        mousedelay--;
 179.961 +                        if (!mousedelay)
 179.962 +                           mousecallback();
 179.963 +                }
 179.964 +                if (sbenable)
 179.965 +                {
 179.966 +                        sbcount-=cycdiff;
 179.967 +                        if (sbcount<0)
 179.968 +                        {
 179.969 +                                sbcount+=sblatcho;
 179.970 +                                pollsb();
 179.971 +                        }
 179.972 +                }
 179.973 +                rtctime-=cycdiff;
 179.974 +                if (rtctime<0)
 179.975 +                {
 179.976 +                        nvr_rtc();
 179.977 +                }
 179.978 +                cycdiff=cycles;
 179.979 +                if (idecallback[0])
 179.980 +                {
 179.981 +                        idecallback[0]--;
 179.982 +                        if (idecallback[0]<=0)
 179.983 +                        {
 179.984 +//                                pclog("IDE time over\n");
 179.985 +                                idecallback[0]=0;
 179.986 +                                callbackide(0);
 179.987 +                        }
 179.988 +                }
 179.989 +}
 179.990 +
 179.991 +
 179.992 +                int firstrepcycle=1;
 179.993 +void cpu_writeport(uint32_t port, uint8_t val) { outb(port,val); }
 179.994 +void rep(int fv)
 179.995 +{
 179.996 +        uint8_t temp;
 179.997 +        int c=CX;
 179.998 +        uint8_t temp2;
 179.999 +        uint16_t tempw,tempw2,tempw3;
179.1000 +        uint16_t ipc=oldpc;//pc-1;
179.1001 +        int changeds=0;
179.1002 +        uint32_t oldds;
179.1003 +        startrep:
179.1004 +        temp=FETCH();
179.1005 +//        if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
179.1006 +//        if (output) printf("REP %02X %04X\n",temp,ipc);
179.1007 +        switch (temp)
179.1008 +        {
179.1009 +                case 0x08:
179.1010 +                pc=ipc+1;
179.1011 +                cycles-=2;
179.1012 +                FETCHCLEAR();
179.1013 +                break;
179.1014 +                case 0x26: /*ES:*/
179.1015 +                oldds=ds;
179.1016 +                ds=es;
179.1017 +                changeds=1;
179.1018 +                cycles-=2;
179.1019 +                goto startrep;
179.1020 +                break;
179.1021 +                case 0x2E: /*CS:*/
179.1022 +                oldds=ds;
179.1023 +                ds=cs;
179.1024 +                changeds=1;
179.1025 +                cycles-=2;
179.1026 +                goto startrep;
179.1027 +                break;
179.1028 +                case 0x36: /*SS:*/
179.1029 +                oldds=ds;
179.1030 +                ds=ss;
179.1031 +                changeds=1;
179.1032 +                cycles-=2;
179.1033 +                goto startrep;
179.1034 +                break;
179.1035 +                case 0x6E: /*REP OUTSB*/
179.1036 +                if (c>0)
179.1037 +                {
179.1038 +                        temp2=readmemb(ds+SI);
179.1039 +                        outb(DX,temp2);
179.1040 +                        if (flags&D_FLAG) SI--;
179.1041 +                        else              SI++;
179.1042 +                        c--;
179.1043 +                        cycles-=5;
179.1044 +                }
179.1045 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1046 +                else firstrepcycle=1;
179.1047 +                break;
179.1048 +                case 0xA4: /*REP MOVSB*/
179.1049 +                while (c>0 && !IRQTEST)
179.1050 +                {
179.1051 +                        temp2=readmemb(ds+SI);
179.1052 +                        writememb(es+DI,temp2);
179.1053 +//                        if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI);
179.1054 +                        if (flags&D_FLAG) { DI--; SI--; }
179.1055 +                        else              { DI++; SI++; }
179.1056 +                        c--;
179.1057 +                        cycles-=((AT)?4:17);
179.1058 +                        clockhardware();
179.1059 +                        FETCHADD(((AT)?4:17)-memcycs);
179.1060 +                }
179.1061 +                if (IRQTEST && c>0) pc=ipc;
179.1062 +//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1063 +//                else firstrepcycle=1;
179.1064 +//                }
179.1065 +                break;
179.1066 +                case 0xA5: /*REP MOVSW*/
179.1067 +                while (c>0 && !IRQTEST)
179.1068 +                {
179.1069 +                        memcycs=0;
179.1070 +                        tempw=readmemw(ds,SI);
179.1071 +                        writememw(es,DI,tempw);
179.1072 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
179.1073 +                        else              { DI+=2; SI+=2; }
179.1074 +                        c--;
179.1075 +                        cycles-=((AT)?4:17);
179.1076 +                        clockhardware();
179.1077 +                        FETCHADD(((AT)?4:17)-memcycs);
179.1078 +                }
179.1079 +                if (IRQTEST && c>0) pc=ipc;
179.1080 +//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1081 +//                else firstrepcycle=1;
179.1082 +//                }
179.1083 +                break;
179.1084 +                case 0xA6: /*REP CMPSB*/
179.1085 +                if (fv) flags|=Z_FLAG;
179.1086 +                else    flags&=~Z_FLAG;
179.1087 +                while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
179.1088 +                {
179.1089 +                        memcycs=0;
179.1090 +                        temp=readmemb(ds+SI);
179.1091 +                        temp2=readmemb(es+DI);
179.1092 +//                        printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc);
179.1093 +                        if (flags&D_FLAG) { DI--; SI--; }
179.1094 +                        else              { DI++; SI++; }
179.1095 +                        c--;
179.1096 +                        if (!AT) cycles-=30;
179.1097 +                        else     cycles-=9;
179.1098 +                        setsub8(temp,temp2);
179.1099 +                        clockhardware();
179.1100 +                        FETCHADD(((AT)?9:30)-memcycs);
179.1101 +                }
179.1102 +                if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
179.1103 +//                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1104 +//                else firstrepcycle=1;
179.1105 +                break;
179.1106 +                case 0xA7: /*REP CMPSW*/
179.1107 +                if (fv) flags|=Z_FLAG;
179.1108 +                else    flags&=~Z_FLAG;
179.1109 +                while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
179.1110 +                {
179.1111 +                        memcycs=0;
179.1112 +                        tempw=readmemw(ds,SI);
179.1113 +                        tempw2=readmemw(es,DI);
179.1114 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
179.1115 +                        else              { DI+=2; SI+=2; }
179.1116 +                        c--;
179.1117 +                        if (!AT) cycles-=30;
179.1118 +                        else     cycles-=9;
179.1119 +                        setsub16(tempw,tempw2);
179.1120 +                        clockhardware();
179.1121 +                        FETCHADD(((AT)?9:30)-memcycs);
179.1122 +                }
179.1123 +                if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
179.1124 +//                if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1125 +//                else firstrepcycle=1;
179.1126 +//                if (firstrepcycle) printf("REP CMPSW  %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2);
179.1127 +                break;
179.1128 +                case 0xAA: /*REP STOSB*/
179.1129 +                while (c>0 && !IRQTEST)
179.1130 +                {
179.1131 +                        memcycs=0;
179.1132 +                        writememb(es+DI,AL);
179.1133 +                        if (flags&D_FLAG) DI--;
179.1134 +                        else              DI++;
179.1135 +                        c--;
179.1136 +                        cycles-=((AT)?3:10);
179.1137 +                        clockhardware();
179.1138 +                        FETCHADD(((AT)?3:10)-memcycs);
179.1139 +                }
179.1140 +                if (IRQTEST && c>0) pc=ipc;
179.1141 +//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1142 +//                else firstrepcycle=1;
179.1143 +                break;
179.1144 +                case 0xAB: /*REP STOSW*/
179.1145 +                while (c>0 && !IRQTEST)
179.1146 +                {
179.1147 +                        memcycs=0;
179.1148 +                        writememw(es,DI,AX);
179.1149 +                        if (flags&D_FLAG) DI-=2;
179.1150 +                        else              DI+=2;
179.1151 +                        c--;
179.1152 +                        cycles-=((AT)?3:10);
179.1153 +                        clockhardware();
179.1154 +                        FETCHADD(((AT)?3:10)-memcycs);
179.1155 +                }
179.1156 +                if (IRQTEST && c>0) pc=ipc;
179.1157 +//                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1158 +//                else firstrepcycle=1;
179.1159 +//                printf("REP STOSW %04X:%04X %04X:%04X %04X %04X\n",CS,pc,ES,DI,AX,CX); }
179.1160 +                break;
179.1161 +                case 0xAC: /*REP LODSB*/
179.1162 +                if (c>0)
179.1163 +                {
179.1164 +                        temp2=readmemb(ds+SI);
179.1165 +                        if (flags&D_FLAG) SI--;
179.1166 +                        else              SI++;
179.1167 +                        c--;
179.1168 +                        cycles-=4;
179.1169 +                }
179.1170 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1171 +                else firstrepcycle=1;
179.1172 +                break;
179.1173 +                case 0xAD: /*REP LODSW*/
179.1174 +                if (c>0)
179.1175 +                {
179.1176 +                        tempw2=readmemw(ds,SI);
179.1177 +                        if (flags&D_FLAG) SI-=2;
179.1178 +                        else              SI+=2;
179.1179 +                        c--;
179.1180 +                        cycles-=4;
179.1181 +                }
179.1182 +                if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1183 +                else firstrepcycle=1;
179.1184 +                break;
179.1185 +                case 0xAE: /*REP SCASB*/
179.1186 +                if (fv) flags|=Z_FLAG;
179.1187 +                else    flags&=~Z_FLAG;
179.1188 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
179.1189 +                {
179.1190 +                        temp2=readmemb(es+DI);
179.1191 +//                        if (output) printf("SCASB %02X %c %02X %05X  ",temp2,temp2,AL,es+DI);
179.1192 +                        setsub8(AL,temp2);
179.1193 +//                        if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2);
179.1194 +                        if (flags&D_FLAG) DI--;
179.1195 +                        else              DI++;
179.1196 +                        c--;
179.1197 +                        cycles-=((AT)?8:15);
179.1198 +                }
179.1199 +//if (output)                printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0))));
179.1200 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1201 +                else firstrepcycle=1;
179.1202 +//                cycles-=120;
179.1203 +                break;
179.1204 +                case 0xAF: /*REP SCASW*/
179.1205 +                if (fv) flags|=Z_FLAG;
179.1206 +                else    flags&=~Z_FLAG;
179.1207 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
179.1208 +                {
179.1209 +                        tempw=readmemw(es,DI);
179.1210 +                        setsub16(AX,tempw);
179.1211 +                        if (flags&D_FLAG) DI-=2;
179.1212 +                        else              DI+=2;
179.1213 +                        c--;
179.1214 +                        cycles-=((AT)?8:15);
179.1215 +                }
179.1216 +                if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))  { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
179.1217 +                else firstrepcycle=1;
179.1218 +                break;
179.1219 +                default:
179.1220 +                        pc=ipc;
179.1221 +                        cycles-=20;
179.1222 +                        FETCHCLEAR();
179.1223 +//                printf("Bad REP %02X\n",temp);
179.1224 +//                dumpregs();
179.1225 +//                exit(-1);
179.1226 +        }
179.1227 +        CX=c;
179.1228 +        if (changeds) ds=oldds;
179.1229 +//        if (pc==ipc) FETCHCLEAR();
179.1230 +}
179.1231 +
179.1232 +
179.1233 +int inhlt=0;
179.1234 +uint16_t lastpc,lastcs;
179.1235 +int firstrepcycle;
179.1236 +int skipnextprint=0;
179.1237 +
179.1238 +
179.1239 +int instime=0,instimer=0;
179.1240 +//#if 0
179.1241 +void execx86(int cycs)
179.1242 +{
179.1243 +        uint8_t temp,temp2;
179.1244 +        uint16_t addr,tempw,tempw2,tempw3,tempw4;
179.1245 +        int8_t offset;
179.1246 +        int tempws;
179.1247 +        uint32_t templ;
179.1248 +        int c;
179.1249 +        int tempi;
179.1250 +        int trap;
179.1251 +        FILE *f;
179.1252 +//        printf("Run x86! %i %i\n",cycles,cycs);
179.1253 +        cycles+=cycs;
179.1254 +//        i86_Execute(cycs);
179.1255 +//        return;
179.1256 +        while (cycles>0)
179.1257 +        {
179.1258 +//                old83=old82;
179.1259 +//                old82=old8;
179.1260 +//                old8=oldpc|(oldcs<<16);
179.1261 +//                if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; }
179.1262 +//                if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime);
179.1263 +                cycdiff=cycles;
179.1264 +                cycles-=nextcyc;
179.1265 +//                if (instime) pclog("Cycles %i %i\n",cycles,cycdiff);
179.1266 +                nextcyc=0;
179.1267 +//        if (output) printf("CLOCK %i %i\n",cycdiff,cycles);
179.1268 +                fetchclocks=0;
179.1269 +                oldcs=CS;
179.1270 +                oldpc=pc;
179.1271 +                opcodestart:
179.1272 +                opcode=FETCH();
179.1273 +                tempc=flags&C_FLAG;
179.1274 +                trap=flags&T_FLAG;
179.1275 +                pc--;
179.1276 +//                output=1;
179.1277 +//                if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat);
179.1278 +//#if 0
179.1279 +                if (output && /*cs<0xF0000 && */!ssegs && (pc<0x43A || pc>0x44A))//opcode!=0x26 && opcode!=0x36 && opcode!=0x2E && opcode!=0x3E)
179.1280 +                {
179.1281 +                        if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
179.1282 +                        {
179.1283 +                                if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X  %02X %02X %02X %02X\n",cs,pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ram[0x413], ram[0x414], ram[0x415], ram[0x416]);
179.1284 +                                skipnextprint=0;
179.1285 +//                                ins++;
179.1286 +                        }
179.1287 +                }
179.1288 +//#endif
179.1289 +                pc++;
179.1290 +                inhlt=0;
179.1291 +//                if (ins==500000) { dumpregs(); exit(0); }*/
179.1292 +                switch (opcode)
179.1293 +                {
179.1294 +                        case 0x00: /*ADD 8,reg*/
179.1295 +                        fetchea();
179.1296 +/*                        if (!rmdat) pc--;
179.1297 +                        if (!rmdat)
179.1298 +                        {
179.1299 +                                fatal("Crashed\n");
179.1300 +//                                clear_keybuf();
179.1301 +//                                readkey();
179.1302 +                        }*/
179.1303 +                        temp=geteab();
179.1304 +                        setadd8(temp,getr8(reg));
179.1305 +                        temp+=getr8(reg);
179.1306 +                        seteab(temp);
179.1307 +                        cycles-=((mod==3)?3:24);
179.1308 +                        break;
179.1309 +                        case 0x01: /*ADD 16,reg*/
179.1310 +                        fetchea();
179.1311 +                        tempw=geteaw();
179.1312 +                        setadd16(tempw,regs[reg].w);
179.1313 +                        tempw+=regs[reg].w;
179.1314 +                        seteaw(tempw);
179.1315 +                        cycles-=((mod==3)?3:24);
179.1316 +                        break;
179.1317 +                        case 0x02: /*ADD reg,8*/
179.1318 +                        fetchea();
179.1319 +                        temp=geteab();
179.1320 +                        setadd8(getr8(reg),temp);
179.1321 +                        setr8(reg,getr8(reg)+temp);
179.1322 +                        cycles-=((mod==3)?3:13);
179.1323 +                        break;
179.1324 +                        case 0x03: /*ADD reg,16*/
179.1325 +                        fetchea();
179.1326 +                        tempw=geteaw();
179.1327 +                        setadd16(regs[reg].w,tempw);
179.1328 +                        regs[reg].w+=tempw;
179.1329 +                        cycles-=((mod==3)?3:13);
179.1330 +                        break;
179.1331 +                        case 0x04: /*ADD AL,#8*/
179.1332 +                        temp=FETCH();
179.1333 +                        setadd8(AL,temp);
179.1334 +                        AL+=temp;
179.1335 +                        cycles-=4;
179.1336 +                        break;
179.1337 +                        case 0x05: /*ADD AX,#16*/
179.1338 +                        tempw=getword();
179.1339 +                        setadd16(AX,tempw);
179.1340 +                        AX+=tempw;
179.1341 +                        cycles-=4;
179.1342 +                        break;
179.1343 +
179.1344 +                        case 0x06: /*PUSH ES*/
179.1345 +                        if (ssegs) ss=oldss;
179.1346 +                        writememw(ss,((SP-2)&0xFFFF),ES);
179.1347 +                        SP-=2;
179.1348 +                        cycles-=14;
179.1349 +                        break;
179.1350 +                        case 0x07: /*POP ES*/
179.1351 +                        if (ssegs) ss=oldss;
179.1352 +                        tempw=readmemw(ss,SP);
179.1353 +                        loadseg(tempw,&_es);
179.1354 +                        SP+=2;
179.1355 +                        cycles-=12;
179.1356 +                        break;
179.1357 +
179.1358 +                        case 0x08: /*OR 8,reg*/
179.1359 +                        fetchea();
179.1360 +                        temp=geteab();
179.1361 +                        temp|=getr8(reg);
179.1362 +                        setznp8(temp);
179.1363 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1364 +                        seteab(temp);
179.1365 +                        cycles-=((mod==3)?3:24);
179.1366 +                        break;
179.1367 +                        case 0x09: /*OR 16,reg*/
179.1368 +                        fetchea();
179.1369 +                        tempw=geteaw();
179.1370 +                        tempw|=regs[reg].w;
179.1371 +                        setznp16(tempw);
179.1372 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1373 +                        seteaw(tempw);
179.1374 +                        cycles-=((mod==3)?3:24);
179.1375 +                        break;
179.1376 +                        case 0x0A: /*OR reg,8*/
179.1377 +                        fetchea();
179.1378 +                        temp=geteab();
179.1379 +                        temp|=getr8(reg);
179.1380 +                        setznp8(temp);
179.1381 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1382 +                        setr8(reg,temp);
179.1383 +                        cycles-=((mod==3)?3:13);
179.1384 +                        break;
179.1385 +                        case 0x0B: /*OR reg,16*/
179.1386 +                        fetchea();
179.1387 +                        tempw=geteaw();
179.1388 +                        tempw|=regs[reg].w;
179.1389 +                        setznp16(tempw);
179.1390 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1391 +                        regs[reg].w=tempw;
179.1392 +                        cycles-=((mod==3)?3:13);
179.1393 +                        break;
179.1394 +                        case 0x0C: /*OR AL,#8*/
179.1395 +                        AL|=FETCH();
179.1396 +                        setznp8(AL);
179.1397 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1398 +                        cycles-=4;
179.1399 +                        break;
179.1400 +                        case 0x0D: /*OR AX,#16*/
179.1401 +                        AX|=getword();
179.1402 +                        setznp16(AX);
179.1403 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1404 +                        cycles-=4;
179.1405 +                        break;
179.1406 +
179.1407 +                        case 0x0E: /*PUSH CS*/
179.1408 +                        if (ssegs) ss=oldss;
179.1409 +                        writememw(ss,((SP-2)&0xFFFF),CS);
179.1410 +                        SP-=2;
179.1411 +                        cycles-=14;
179.1412 +                        break;
179.1413 +                        case 0x0F: /*POP CS - 8088/8086 only*/
179.1414 +                        if (ssegs) ss=oldss;
179.1415 +                        tempw=readmemw(ss,SP);
179.1416 +                        loadseg(tempw,&_cs);
179.1417 +                        SP+=2;
179.1418 +                        cycles-=12;
179.1419 +                        break;
179.1420 +
179.1421 +                        case 0x10: /*ADC 8,reg*/
179.1422 +                        fetchea();
179.1423 +                        temp=geteab();
179.1424 +                        temp2=getr8(reg);
179.1425 +                        setadc8(temp,temp2);
179.1426 +                        temp+=temp2+tempc;
179.1427 +                        seteab(temp);
179.1428 +                        cycles-=((mod==3)?3:24);
179.1429 +                        break;
179.1430 +                        case 0x11: /*ADC 16,reg*/
179.1431 +                        fetchea();
179.1432 +                        tempw=geteaw();
179.1433 +                        tempw2=regs[reg].w;
179.1434 +                        setadc16(tempw,tempw2);
179.1435 +                        tempw+=tempw2+tempc;
179.1436 +                        seteaw(tempw);
179.1437 +                        cycles-=((mod==3)?3:24);
179.1438 +                        break;
179.1439 +                        case 0x12: /*ADC reg,8*/
179.1440 +                        fetchea();
179.1441 +                        temp=geteab();
179.1442 +                        setadc8(getr8(reg),temp);
179.1443 +                        setr8(reg,getr8(reg)+temp+tempc);
179.1444 +                        cycles-=((mod==3)?3:13);
179.1445 +                        break;
179.1446 +                        case 0x13: /*ADC reg,16*/
179.1447 +                        fetchea();
179.1448 +                        tempw=geteaw();
179.1449 +                        setadc16(regs[reg].w,tempw);
179.1450 +                        regs[reg].w+=tempw+tempc;
179.1451 +                        cycles-=((mod==3)?3:13);
179.1452 +                        break;
179.1453 +                        case 0x14: /*ADC AL,#8*/
179.1454 +                        tempw=FETCH();
179.1455 +                        setadc8(AL,tempw);
179.1456 +                        AL+=tempw+tempc;
179.1457 +                        cycles-=4;
179.1458 +                        break;
179.1459 +                        case 0x15: /*ADC AX,#16*/
179.1460 +                        tempw=getword();
179.1461 +                        setadc16(AX,tempw);
179.1462 +                        AX+=tempw+tempc;
179.1463 +                        cycles-=4;
179.1464 +                        break;
179.1465 +
179.1466 +                        case 0x16: /*PUSH SS*/
179.1467 +                        if (ssegs) ss=oldss;
179.1468 +                        writememw(ss,((SP-2)&0xFFFF),SS);
179.1469 +                        SP-=2;
179.1470 +                        cycles-=14;
179.1471 +                        break;
179.1472 +                        case 0x17: /*POP SS*/
179.1473 +                        if (ssegs) ss=oldss;
179.1474 +                        tempw=readmemw(ss,SP);
179.1475 +                        loadseg(tempw,&_ss);
179.1476 +                        SP+=2;
179.1477 +                        noint=1;
179.1478 +                        cycles-=12;
179.1479 +//                        output=1;
179.1480 +                        break;
179.1481 +
179.1482 +                        case 0x18: /*SBB 8,reg*/
179.1483 +                        fetchea();
179.1484 +                        temp=geteab();
179.1485 +                        temp2=getr8(reg);
179.1486 +                        setsbc8(temp,temp2);
179.1487 +                        temp-=(temp2+tempc);
179.1488 +                        seteab(temp);
179.1489 +                        cycles-=((mod==3)?3:24);
179.1490 +                        break;
179.1491 +                        case 0x19: /*SBB 16,reg*/
179.1492 +                        fetchea();
179.1493 +                        tempw=geteaw();
179.1494 +                        tempw2=regs[reg].w;
179.1495 +//                        printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
179.1496 +                        setsbc16(tempw,tempw2);
179.1497 +                        tempw-=(tempw2+tempc);
179.1498 +                        seteaw(tempw);
179.1499 +                        cycles-=((mod==3)?3:24);
179.1500 +                        break;
179.1501 +                        case 0x1A: /*SBB reg,8*/
179.1502 +                        fetchea();
179.1503 +                        temp=geteab();
179.1504 +                        setsbc8(getr8(reg),temp);
179.1505 +                        setr8(reg,getr8(reg)-(temp+tempc));
179.1506 +                        cycles-=((mod==3)?3:13);
179.1507 +                        break;
179.1508 +                        case 0x1B: /*SBB reg,16*/
179.1509 +                        fetchea();
179.1510 +                        tempw=geteaw();
179.1511 +                        tempw2=regs[reg].w;
179.1512 +//                        printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
179.1513 +                        setsbc16(tempw2,tempw);
179.1514 +                        tempw2-=(tempw+tempc);
179.1515 +                        regs[reg].w=tempw2;
179.1516 +                        cycles-=((mod==3)?3:13);
179.1517 +                        break;
179.1518 +                        case 0x1C: /*SBB AL,#8*/
179.1519 +                        temp=FETCH();
179.1520 +                        setsbc8(AL,temp);
179.1521 +                        AL-=(temp+tempc);
179.1522 +                        cycles-=4;
179.1523 +                        break;
179.1524 +                        case 0x1D: /*SBB AX,#16*/
179.1525 +                        tempw=getword();
179.1526 +                        setsbc16(AX,tempw);
179.1527 +                        AX-=(tempw+tempc);
179.1528 +                        cycles-=4;
179.1529 +                        break;
179.1530 +
179.1531 +                        case 0x1E: /*PUSH DS*/
179.1532 +                        if (ssegs) ss=oldss;
179.1533 +                        writememw(ss,((SP-2)&0xFFFF),DS);
179.1534 +                        SP-=2;
179.1535 +                        cycles-=14;
179.1536 +                        break;
179.1537 +                        case 0x1F: /*POP DS*/
179.1538 +                        if (ssegs) ss=oldss;
179.1539 +                        tempw=readmemw(ss,SP);
179.1540 +                        loadseg(tempw,&_ds);
179.1541 +                        if (ssegs) oldds=ds;
179.1542 +                        SP+=2;
179.1543 +                        cycles-=12;
179.1544 +                        break;
179.1545 +
179.1546 +                        case 0x20: /*AND 8,reg*/
179.1547 +                        fetchea();
179.1548 +                        temp=geteab();
179.1549 +                        temp&=getr8(reg);
179.1550 +                        setznp8(temp);
179.1551 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1552 +                        seteab(temp);
179.1553 +                        cycles-=((mod==3)?3:24);
179.1554 +                        break;
179.1555 +                        case 0x21: /*AND 16,reg*/
179.1556 +                        fetchea();
179.1557 +                        tempw=geteaw();
179.1558 +                        tempw&=regs[reg].w;
179.1559 +                        setznp16(tempw);
179.1560 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1561 +                        seteaw(tempw);
179.1562 +                        cycles-=((mod==3)?3:24);
179.1563 +                        break;
179.1564 +                        case 0x22: /*AND reg,8*/
179.1565 +                        fetchea();
179.1566 +                        temp=geteab();
179.1567 +                        temp&=getr8(reg);
179.1568 +                        setznp8(temp);
179.1569 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1570 +                        setr8(reg,temp);
179.1571 +                        cycles-=((mod==3)?3:13);
179.1572 +                        break;
179.1573 +                        case 0x23: /*AND reg,16*/
179.1574 +                        fetchea();
179.1575 +                        tempw=geteaw();
179.1576 +                        tempw&=regs[reg].w;
179.1577 +                        setznp16(tempw);
179.1578 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1579 +                        regs[reg].w=tempw;
179.1580 +                        cycles-=((mod==3)?3:13);
179.1581 +                        break;
179.1582 +                        case 0x24: /*AND AL,#8*/
179.1583 +                        AL&=FETCH();
179.1584 +                        setznp8(AL);
179.1585 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1586 +                        cycles-=4;
179.1587 +                        break;
179.1588 +                        case 0x25: /*AND AX,#16*/
179.1589 +                        AX&=getword();
179.1590 +                        setznp16(AX);
179.1591 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1592 +                        cycles-=4;
179.1593 +                        break;
179.1594 +
179.1595 +                        case 0x26: /*ES:*/
179.1596 +                        oldss=ss;
179.1597 +                        oldds=ds;
179.1598 +                        ds=ss=es;
179.1599 +                        ssegs=2;
179.1600 +                        cycles-=4;
179.1601 +                        goto opcodestart;
179.1602 +//                        break;
179.1603 +
179.1604 +                        case 0x27: /*DAA*/
179.1605 +                        if ((flags&A_FLAG) || ((AL&0xF)>9))
179.1606 +                        {
179.1607 +                                tempi=((uint16_t)AL)+6;
179.1608 +                                AL+=6;
179.1609 +                                flags|=A_FLAG;
179.1610 +                                if (tempi&0x100) flags|=C_FLAG;
179.1611 +                        }
179.1612 +//                        else
179.1613 +//                           flags&=~A_FLAG;
179.1614 +                        if ((flags&C_FLAG) || (AL>0x9F))
179.1615 +                        {
179.1616 +                                AL+=0x60;
179.1617 +                                flags|=C_FLAG;
179.1618 +                        }
179.1619 +//                        else
179.1620 +//                           flags&=~C_FLAG;
179.1621 +                        setznp8(AL);
179.1622 +                        cycles-=4;
179.1623 +                        break;
179.1624 +
179.1625 +                        case 0x28: /*SUB 8,reg*/
179.1626 +                        fetchea();
179.1627 +                        temp=geteab();
179.1628 +                        setsub8(temp,getr8(reg));
179.1629 +                        temp-=getr8(reg);
179.1630 +                        seteab(temp);
179.1631 +                        cycles-=((mod==3)?3:24);
179.1632 +                        break;
179.1633 +                        case 0x29: /*SUB 16,reg*/
179.1634 +                        fetchea();
179.1635 +                        tempw=geteaw();
179.1636 +//                        printf("%04X:%04X  %04X-%04X\n",cs>>4,pc,tempw,regs[reg].w);
179.1637 +                        setsub16(tempw,regs[reg].w);
179.1638 +                        tempw-=regs[reg].w;
179.1639 +                        seteaw(tempw);
179.1640 +                        cycles-=((mod==3)?3:24);
179.1641 +                        break;
179.1642 +                        case 0x2A: /*SUB reg,8*/
179.1643 +                        fetchea();
179.1644 +                        temp=geteab();
179.1645 +                        setsub8(getr8(reg),temp);
179.1646 +                        setr8(reg,getr8(reg)-temp);
179.1647 +                        cycles-=((mod==3)?3:13);
179.1648 +                        break;
179.1649 +                        case 0x2B: /*SUB reg,16*/
179.1650 +                        fetchea();
179.1651 +                        tempw=geteaw();
179.1652 +//                        printf("%04X:%04X  %04X-%04X\n",cs>>4,pc,regs[reg].w,tempw);
179.1653 +                        setsub16(regs[reg].w,tempw);
179.1654 +                        regs[reg].w-=tempw;
179.1655 +                        cycles-=((mod==3)?3:13);
179.1656 +                        break;
179.1657 +                        case 0x2C: /*SUB AL,#8*/
179.1658 +                        temp=FETCH();
179.1659 +                        setsub8(AL,temp);
179.1660 +                        AL-=temp;
179.1661 +                        cycles-=4;
179.1662 +                        break;
179.1663 +                        case 0x2D: /*SUB AX,#16*/
179.1664 +//                        printf("INS %i\n",ins);
179.1665 +//                        output=1;
179.1666 +                        tempw=getword();
179.1667 +                        setsub16(AX,tempw);
179.1668 +                        AX-=tempw;
179.1669 +                        cycles-=4;
179.1670 +                        break;
179.1671 +                        case 0x2E: /*CS:*/
179.1672 +                        oldss=ss;
179.1673 +                        oldds=ds;
179.1674 +                        ds=ss=cs;
179.1675 +                        ssegs=2;
179.1676 +                        cycles-=4;
179.1677 +                        goto opcodestart;
179.1678 +                        case 0x2F: /*DAS*/
179.1679 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
179.1680 +                        {
179.1681 +                                tempi=((uint16_t)AL)-6;
179.1682 +                                AL-=6;
179.1683 +                                flags|=A_FLAG;
179.1684 +                                if (tempi&0x100) flags|=C_FLAG;
179.1685 +                        }
179.1686 +//                        else
179.1687 +//                           flags&=~A_FLAG;
179.1688 +                        if ((flags&C_FLAG)||(AL>0x9F))
179.1689 +                        {
179.1690 +                                AL-=0x60;
179.1691 +                                flags|=C_FLAG;
179.1692 +                        }
179.1693 +//                        else
179.1694 +//                           flags&=~C_FLAG;
179.1695 +                        setznp8(AL);
179.1696 +                        cycles-=4;
179.1697 +                        break;
179.1698 +                        case 0x30: /*XOR 8,reg*/
179.1699 +                        fetchea();
179.1700 +                        temp=geteab();
179.1701 +                        temp^=getr8(reg);
179.1702 +                        setznp8(temp);
179.1703 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1704 +                        seteab(temp);
179.1705 +                        cycles-=((mod==3)?3:24);
179.1706 +                        break;
179.1707 +                        case 0x31: /*XOR 16,reg*/
179.1708 +                        fetchea();
179.1709 +                        tempw=geteaw();
179.1710 +                        tempw^=regs[reg].w;
179.1711 +                        setznp16(tempw);
179.1712 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1713 +                        seteaw(tempw);
179.1714 +                        cycles-=((mod==3)?3:24);
179.1715 +                        break;
179.1716 +                        case 0x32: /*XOR reg,8*/
179.1717 +                        fetchea();
179.1718 +                        temp=geteab();
179.1719 +                        temp^=getr8(reg);
179.1720 +                        setznp8(temp);
179.1721 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1722 +                        setr8(reg,temp);
179.1723 +                        cycles-=((mod==3)?3:13);
179.1724 +                        break;
179.1725 +                        case 0x33: /*XOR reg,16*/
179.1726 +                        fetchea();
179.1727 +                        tempw=geteaw();
179.1728 +                        tempw^=regs[reg].w;
179.1729 +                        setznp16(tempw);
179.1730 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1731 +                        regs[reg].w=tempw;
179.1732 +                        cycles-=((mod==3)?3:13);
179.1733 +                        break;
179.1734 +                        case 0x34: /*XOR AL,#8*/
179.1735 +                        AL^=FETCH();
179.1736 +                        setznp8(AL);
179.1737 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1738 +                        cycles-=4;
179.1739 +                        break;
179.1740 +                        case 0x35: /*XOR AX,#16*/
179.1741 +                        AX^=getword();
179.1742 +                        setznp16(AX);
179.1743 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1744 +                        cycles-=4;
179.1745 +                        break;
179.1746 +
179.1747 +                        case 0x36: /*SS:*/
179.1748 +                        oldss=ss;
179.1749 +                        oldds=ds;
179.1750 +                        ds=ss=ss;
179.1751 +                        ssegs=2;
179.1752 +                        cycles-=4;
179.1753 +                        goto opcodestart;
179.1754 +//                        break;
179.1755 +
179.1756 +                        case 0x37: /*AAA*/
179.1757 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
179.1758 +                        {
179.1759 +                                AL+=6;
179.1760 +                                AH++;
179.1761 +                                flags|=(A_FLAG|C_FLAG);
179.1762 +                        }
179.1763 +                        else
179.1764 +                           flags&=~(A_FLAG|C_FLAG);
179.1765 +                        AL&=0xF;
179.1766 +                        cycles-=8;
179.1767 +                        break;
179.1768 +
179.1769 +                        case 0x38: /*CMP 8,reg*/
179.1770 +                        fetchea();
179.1771 +                        temp=geteab();
179.1772 +//                        if (output) printf("CMP %02X-%02X\n",temp,getr8(reg));
179.1773 +                        setsub8(temp,getr8(reg));
179.1774 +                        cycles-=((mod==3)?3:13);
179.1775 +                        break;
179.1776 +                        case 0x39: /*CMP 16,reg*/
179.1777 +                        fetchea();
179.1778 +                        tempw=geteaw();
179.1779 +//                        if (output) printf("CMP %04X-%04X\n",tempw,regs[reg].w);
179.1780 +                        setsub16(tempw,regs[reg].w);
179.1781 +                        cycles-=((mod==3)?3:13);
179.1782 +                        break;
179.1783 +                        case 0x3A: /*CMP reg,8*/
179.1784 +                        fetchea();
179.1785 +                        temp=geteab();
179.1786 +//                        if (output) printf("CMP %02X-%02X\n",getr8(reg),temp);
179.1787 +                        setsub8(getr8(reg),temp);
179.1788 +                        cycles-=((mod==3)?3:13);
179.1789 +                        break;
179.1790 +                        case 0x3B: /*CMP reg,16*/
179.1791 +                        fetchea();
179.1792 +                        tempw=geteaw();
179.1793 +//                        printf("CMP %04X-%04X\n",regs[reg].w,tempw);
179.1794 +                        setsub16(regs[reg].w,tempw);
179.1795 +                        cycles-=((mod==3)?3:13);
179.1796 +                        break;
179.1797 +                        case 0x3C: /*CMP AL,#8*/
179.1798 +                        temp=FETCH();
179.1799 +                        setsub8(AL,temp);
179.1800 +                        cycles-=4;
179.1801 +                        break;
179.1802 +                        case 0x3D: /*CMP AX,#16*/
179.1803 +                        tempw=getword();
179.1804 +                        setsub16(AX,tempw);
179.1805 +                        cycles-=4;
179.1806 +                        break;
179.1807 +
179.1808 +                        case 0x3E: /*DS:*/
179.1809 +                        oldss=ss;
179.1810 +                        oldds=ds;
179.1811 +                        ds=ss=ds;
179.1812 +                        ssegs=2;
179.1813 +                        cycles-=4;
179.1814 +                        goto opcodestart;
179.1815 +//                        break;
179.1816 +
179.1817 +                        case 0x3F: /*AAS*/
179.1818 +                        if ((flags&A_FLAG)||((AL&0xF)>9))
179.1819 +                        {
179.1820 +                                AL-=6;
179.1821 +                                AH--;
179.1822 +                                flags|=(A_FLAG|C_FLAG);
179.1823 +                        }
179.1824 +                        else
179.1825 +                           flags&=~(A_FLAG|C_FLAG);
179.1826 +                        AL&=0xF;
179.1827 +                        cycles-=8;
179.1828 +                        break;
179.1829 +
179.1830 +                        case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
179.1831 +                        case 0x44: case 0x45: case 0x46: case 0x47:
179.1832 +                        setadd16nc(regs[opcode&7].w,1);
179.1833 +                        regs[opcode&7].w++;
179.1834 +                        cycles-=3;
179.1835 +                        break;
179.1836 +                        case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/
179.1837 +                        case 0x4C: case 0x4D: case 0x4E: case 0x4F:
179.1838 +                        setsub16nc(regs[opcode&7].w,1);
179.1839 +                        regs[opcode&7].w--;
179.1840 +                        cycles-=3;
179.1841 +                        break;
179.1842 +
179.1843 +                        case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
179.1844 +                        case 0x54: case 0x55: case 0x56: case 0x57:
179.1845 +                        if (ssegs) ss=oldss;
179.1846 +                        SP-=2;
179.1847 +                        writememw(ss,SP,regs[opcode&7].w);
179.1848 +                        cycles-=15;
179.1849 +                        break;
179.1850 +                        case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/
179.1851 +                        case 0x5C: case 0x5D: case 0x5E: case 0x5F:
179.1852 +                        if (ssegs) ss=oldss;
179.1853 +                        SP+=2;
179.1854 +                        regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF);
179.1855 +                        cycles-=12;
179.1856 +                        break;
179.1857 +
179.1858 +
179.1859 +                        case 0x70: /*JO*/
179.1860 +                        offset=(int8_t)FETCH();
179.1861 +                        if (flags&V_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1862 +                        cycles-=4;
179.1863 +                        break;
179.1864 +                        case 0x71: /*JNO*/
179.1865 +                        offset=(int8_t)FETCH();
179.1866 +                        if (!(flags&V_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1867 +                        cycles-=4;
179.1868 +                        break;
179.1869 +                        case 0x72: /*JB*/
179.1870 +                        offset=(int8_t)FETCH();
179.1871 +                        if (flags&C_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1872 +                        cycles-=4;
179.1873 +                        break;
179.1874 +                        case 0x73: /*JNB*/
179.1875 +                        offset=(int8_t)FETCH();
179.1876 +                        if (!(flags&C_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1877 +                        cycles-=4;
179.1878 +                        break;
179.1879 +                        case 0x74: /*JE*/
179.1880 +                        offset=(int8_t)FETCH();
179.1881 +                        if (flags&Z_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1882 +                        cycles-=4;
179.1883 +                        break;
179.1884 +                        case 0x75: /*JNE*/
179.1885 +                        offset=(int8_t)FETCH();
179.1886 +                        cycles-=4;
179.1887 +                        if (!(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1888 +                        break;
179.1889 +                        case 0x76: /*JBE*/
179.1890 +                        offset=(int8_t)FETCH();
179.1891 +                        if (flags&(C_FLAG|Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1892 +                        cycles-=4;
179.1893 +                        break;
179.1894 +                        case 0x77: /*JNBE*/
179.1895 +                        offset=(int8_t)FETCH();
179.1896 +                        if (!(flags&(C_FLAG|Z_FLAG))) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1897 +                        cycles-=4;
179.1898 +                        break;
179.1899 +                        case 0x78: /*JS*/
179.1900 +                        offset=(int8_t)FETCH();
179.1901 +                        if (flags&N_FLAG)  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1902 +                        cycles-=4;
179.1903 +                        break;
179.1904 +                        case 0x79: /*JNS*/
179.1905 +                        offset=(int8_t)FETCH();
179.1906 +                        if (!(flags&N_FLAG))  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1907 +                        cycles-=4;
179.1908 +                        break;
179.1909 +                        case 0x7A: /*JP*/
179.1910 +                        offset=(int8_t)FETCH();
179.1911 +                        if (flags&P_FLAG)  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1912 +                        cycles-=4;
179.1913 +                        break;
179.1914 +                        case 0x7B: /*JNP*/
179.1915 +                        offset=(int8_t)FETCH();
179.1916 +                        if (!(flags&P_FLAG))  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1917 +                        cycles-=4;
179.1918 +                        break;
179.1919 +                        case 0x7C: /*JL*/
179.1920 +                        offset=(int8_t)FETCH();
179.1921 +                        temp=(flags&N_FLAG)?1:0;
179.1922 +                        temp2=(flags&V_FLAG)?1:0;
179.1923 +                        if (temp!=temp2)  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1924 +                        cycles-=4;
179.1925 +                        break;
179.1926 +                        case 0x7D: /*JNL*/
179.1927 +                        offset=(int8_t)FETCH();
179.1928 +                        temp=(flags&N_FLAG)?1:0;
179.1929 +                        temp2=(flags&V_FLAG)?1:0;
179.1930 +                        if (temp==temp2)  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1931 +                        cycles-=4;
179.1932 +                        break;
179.1933 +                        case 0x7E: /*JLE*/
179.1934 +                        offset=(int8_t)FETCH();
179.1935 +                        temp=(flags&N_FLAG)?1:0;
179.1936 +                        temp2=(flags&V_FLAG)?1:0;
179.1937 +                        if ((flags&Z_FLAG) || (temp!=temp2))  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1938 +                        cycles-=4;
179.1939 +                        break;
179.1940 +                        case 0x7F: /*JNLE*/
179.1941 +                        offset=(int8_t)FETCH();
179.1942 +                        temp=(flags&N_FLAG)?1:0;
179.1943 +                        temp2=(flags&V_FLAG)?1:0;
179.1944 +                        if (!((flags&Z_FLAG) || (temp!=temp2)))  { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.1945 +                        cycles-=4;
179.1946 +                        break;
179.1947 +
179.1948 +                        case 0x80: case 0x82:
179.1949 +                        fetchea();
179.1950 +                        temp=geteab();
179.1951 +                        temp2=FETCH();
179.1952 +                        switch (rmdat&0x38)
179.1953 +                        {
179.1954 +                                case 0x00: /*ADD b,#8*/
179.1955 +                                setadd8(temp,temp2);
179.1956 +                                seteab(temp+temp2);
179.1957 +                                cycles-=((mod==3)?4:23);
179.1958 +                                break;
179.1959 +                                case 0x08: /*OR b,#8*/
179.1960 +                                temp|=temp2;
179.1961 +                                setznp8(temp);
179.1962 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1963 +                                seteab(temp);
179.1964 +                                cycles-=((mod==3)?4:23);
179.1965 +                                break;
179.1966 +                                case 0x10: /*ADC b,#8*/
179.1967 +//                                temp2+=(flags&C_FLAG);
179.1968 +                                setadc8(temp,temp2);
179.1969 +                                seteab(temp+temp2+tempc);
179.1970 +                                cycles-=((mod==3)?4:23);
179.1971 +                                break;
179.1972 +                                case 0x18: /*SBB b,#8*/
179.1973 +//                                temp2+=(flags&C_FLAG);
179.1974 +                                setsbc8(temp,temp2);
179.1975 +                                seteab(temp-(temp2+tempc));
179.1976 +                                cycles-=((mod==3)?4:23);
179.1977 +                                break;
179.1978 +                                case 0x20: /*AND b,#8*/
179.1979 +                                temp&=temp2;
179.1980 +                                setznp8(temp);
179.1981 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1982 +                                seteab(temp);
179.1983 +                                cycles-=((mod==3)?4:23);
179.1984 +                                break;
179.1985 +                                case 0x28: /*SUB b,#8*/
179.1986 +                                setsub8(temp,temp2);
179.1987 +                                seteab(temp-temp2);
179.1988 +                                cycles-=((mod==3)?4:23);
179.1989 +                                break;
179.1990 +                                case 0x30: /*XOR b,#8*/
179.1991 +                                temp^=temp2;
179.1992 +                                setznp8(temp);
179.1993 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.1994 +                                seteab(temp);
179.1995 +                                cycles-=((mod==3)?4:23);
179.1996 +                                break;
179.1997 +                                case 0x38: /*CMP b,#8*/
179.1998 +                                setsub8(temp,temp2);
179.1999 +                                cycles-=((mod==3)?4:14);
179.2000 +                                break;
179.2001 +
179.2002 +//                                default:
179.2003 +//                                printf("Bad 80 opcode %02X\n",rmdat&0x38);
179.2004 +//                                dumpregs();
179.2005 +//                                exit(-1);
179.2006 +                        }
179.2007 +                        break;
179.2008 +
179.2009 +                        case 0x81:
179.2010 +                        fetchea();
179.2011 +                        tempw=geteaw();
179.2012 +                        tempw2=getword();
179.2013 +                        switch (rmdat&0x38)
179.2014 +                        {
179.2015 +                                case 0x00: /*ADD w,#16*/
179.2016 +                                setadd16(tempw,tempw2);
179.2017 +                                tempw+=tempw2;
179.2018 +                                seteaw(tempw);
179.2019 +                                cycles-=((mod==3)?4:23);
179.2020 +                                break;
179.2021 +                                case 0x08: /*OR w,#16*/
179.2022 +                                tempw|=tempw2;
179.2023 +                                setznp16(tempw);
179.2024 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2025 +                                seteaw(tempw);
179.2026 +                                cycles-=((mod==3)?4:23);
179.2027 +                                break;
179.2028 +                                case 0x10: /*ADC w,#16*/
179.2029 +//                                tempw2+=(flags&C_FLAG);
179.2030 +                                setadc16(tempw,tempw2);
179.2031 +                                tempw+=tempw2+tempc;
179.2032 +                                seteaw(tempw);
179.2033 +                                cycles-=((mod==3)?4:23);
179.2034 +                                break;
179.2035 +                                case 0x20: /*AND w,#16*/
179.2036 +                                tempw&=tempw2;
179.2037 +                                setznp16(tempw);
179.2038 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2039 +                                seteaw(tempw);
179.2040 +                                cycles-=((mod==3)?4:23);
179.2041 +                                break;
179.2042 +                                case 0x18: /*SBB w,#16*/
179.2043 +//                                tempw2+=(flags&C_FLAG);
179.2044 +                                setsbc16(tempw,tempw2);
179.2045 +                                seteaw(tempw-(tempw2+tempc));
179.2046 +                                cycles-=((mod==3)?4:23);
179.2047 +                                break;
179.2048 +                                case 0x28: /*SUB w,#16*/
179.2049 +                                setsub16(tempw,tempw2);
179.2050 +                                tempw-=tempw2;
179.2051 +                                seteaw(tempw);
179.2052 +                                cycles-=((mod==3)?4:23);
179.2053 +                                break;
179.2054 +                                case 0x30: /*XOR w,#16*/
179.2055 +                                tempw^=tempw2;
179.2056 +                                setznp16(tempw);
179.2057 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2058 +                                seteaw(tempw);
179.2059 +                                cycles-=((mod==3)?4:23);
179.2060 +                                break;
179.2061 +                                case 0x38: /*CMP w,#16*/
179.2062 +//                                printf("CMP %04X %04X\n",tempw,tempw2);
179.2063 +                                setsub16(tempw,tempw2);
179.2064 +                                cycles-=((mod==3)?4:14);
179.2065 +                                break;
179.2066 +
179.2067 +//                                default:
179.2068 +//                                printf("Bad 81 opcode %02X\n",rmdat&0x38);
179.2069 +//                                dumpregs();
179.2070 +//                                exit(-1);
179.2071 +                        }
179.2072 +                        break;
179.2073 +
179.2074 +                        case 0x83:
179.2075 +                        fetchea();
179.2076 +                        tempw=geteaw();
179.2077 +                        tempw2=FETCH();
179.2078 +                        if (tempw2&0x80) tempw2|=0xFF00;
179.2079 +                        switch (rmdat&0x38)
179.2080 +                        {
179.2081 +                                case 0x00: /*ADD w,#8*/
179.2082 +                                setadd16(tempw,tempw2);
179.2083 +                                tempw+=tempw2;
179.2084 +                                seteaw(tempw);
179.2085 +                                cycles-=((mod==3)?4:23);
179.2086 +                                break;
179.2087 +                                case 0x08: /*OR w,#8*/
179.2088 +                                tempw|=tempw2;
179.2089 +                                setznp16(tempw);
179.2090 +                                seteaw(tempw);
179.2091 +                                flags&=~(C_FLAG|A_FLAG|V_FLAG);
179.2092 +                                cycles-=((mod==3)?4:23);
179.2093 +                                break;
179.2094 +                                case 0x10: /*ADC w,#8*/
179.2095 +//                                tempw2+=(flags&C_FLAG);
179.2096 +                                setadc16(tempw,tempw2);
179.2097 +                                tempw+=tempw2+tempc;
179.2098 +                                seteaw(tempw);
179.2099 +                                cycles-=((mod==3)?4:23);
179.2100 +                                break;
179.2101 +                                case 0x18: /*SBB w,#8*/
179.2102 +//                                tempw2+=(flags&C_FLAG);
179.2103 +                                setsbc16(tempw,tempw2);
179.2104 +                                tempw-=(tempw2+tempc);
179.2105 +                                seteaw(tempw);
179.2106 +                                cycles-=((mod==3)?4:23);
179.2107 +                                break;
179.2108 +                                case 0x20: /*AND w,#8*/
179.2109 +                                tempw&=tempw2;
179.2110 +                                setznp16(tempw);
179.2111 +                                seteaw(tempw);
179.2112 +                                cycles-=((mod==3)?4:23);
179.2113 +                                flags&=~(C_FLAG|A_FLAG|V_FLAG);
179.2114 +                                break;
179.2115 +                                case 0x28: /*SUB w,#8*/
179.2116 +                                setsub16(tempw,tempw2);
179.2117 +                                tempw-=tempw2;
179.2118 +                                seteaw(tempw);
179.2119 +                                cycles-=((mod==3)?4:23);
179.2120 +                                break;
179.2121 +                                case 0x30: /*XOR w,#8*/
179.2122 +                                tempw^=tempw2;
179.2123 +                                setznp16(tempw);
179.2124 +                                seteaw(tempw);
179.2125 +                                cycles-=((mod==3)?4:23);
179.2126 +                                flags&=~(C_FLAG|A_FLAG|V_FLAG);
179.2127 +                                break;
179.2128 +                                case 0x38: /*CMP w,#8*/
179.2129 +                                setsub16(tempw,tempw2);
179.2130 +                                cycles-=((mod==3)?4:14);
179.2131 +                                break;
179.2132 +
179.2133 +//                                default:
179.2134 +//                                printf("Bad 83 opcode %02X\n",rmdat&0x38);
179.2135 +//                                dumpregs();
179.2136 +//                                exit(-1);
179.2137 +                        }
179.2138 +                        break;
179.2139 +
179.2140 +                        case 0x84: /*TEST b,reg*/
179.2141 +                        fetchea();
179.2142 +                        temp=geteab();
179.2143 +                        temp2=getr8(reg);
179.2144 +                        setznp8(temp&temp2);
179.2145 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2146 +                        cycles-=((mod==3)?3:13);
179.2147 +                        break;
179.2148 +                        case 0x85: /*TEST w,reg*/
179.2149 +                        fetchea();
179.2150 +                        tempw=geteaw();
179.2151 +                        tempw2=regs[reg].w;
179.2152 +                        setznp16(tempw&tempw2);
179.2153 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2154 +                        cycles-=((mod==3)?3:13);
179.2155 +                        break;
179.2156 +                        case 0x86: /*XCHG b,reg*/
179.2157 +                        fetchea();
179.2158 +                        temp=geteab();
179.2159 +                        seteab(getr8(reg));
179.2160 +                        setr8(reg,temp);
179.2161 +                        cycles-=((mod==3)?4:25);
179.2162 +                        break;
179.2163 +                        case 0x87: /*XCHG w,reg*/
179.2164 +                        fetchea();
179.2165 +                        tempw=geteaw();
179.2166 +                        seteaw(regs[reg].w);
179.2167 +                        regs[reg].w=tempw;
179.2168 +                        cycles-=((mod==3)?4:25);
179.2169 +                        break;
179.2170 +
179.2171 +                        case 0x88: /*MOV b,reg*/
179.2172 +                        fetchea();
179.2173 +                        seteab(getr8(reg));
179.2174 +                        cycles-=((mod==3)?2:13);
179.2175 +                        break;
179.2176 +                        case 0x89: /*MOV w,reg*/
179.2177 +                        fetchea();
179.2178 +                        seteaw(regs[reg].w);
179.2179 +                        cycles-=((mod==3)?2:13);
179.2180 +                        break;
179.2181 +                        case 0x8A: /*MOV reg,b*/
179.2182 +                        fetchea();
179.2183 +                        temp=geteab();
179.2184 +                        setr8(reg,temp);
179.2185 +                        cycles-=((mod==3)?2:12);
179.2186 +                        break;
179.2187 +                        case 0x8B: /*MOV reg,w*/
179.2188 +                        fetchea();
179.2189 +                        tempw=geteaw();
179.2190 +                        regs[reg].w=tempw;
179.2191 +                        cycles-=((mod==3)?2:12);
179.2192 +                        break;
179.2193 +
179.2194 +                        case 0x8C: /*MOV w,sreg*/
179.2195 +                        fetchea();
179.2196 +                        switch (rmdat&0x38)
179.2197 +                        {
179.2198 +                                case 0x00: /*ES*/
179.2199 +                                seteaw(ES);
179.2200 +                                break;
179.2201 +                                case 0x08: /*CS*/
179.2202 +                                seteaw(CS);
179.2203 +                                break;
179.2204 +                                case 0x18: /*DS*/
179.2205 +                                if (ssegs) ds=oldds;
179.2206 +                                seteaw(DS);
179.2207 +                                break;
179.2208 +                                case 0x10: /*SS*/
179.2209 +                                if (ssegs) ss=oldss;
179.2210 +                                seteaw(SS);
179.2211 +                                break;
179.2212 +                        }
179.2213 +                        cycles-=((mod==3)?2:13);
179.2214 +                        break;
179.2215 +
179.2216 +                        case 0x8D: /*LEA*/
179.2217 +                        fetchea();
179.2218 +                        regs[reg].w=eaaddr;
179.2219 +                        cycles-=2;
179.2220 +                        break;
179.2221 +
179.2222 +                        case 0x8E: /*MOV sreg,w*/
179.2223 +//                        if (output) printf("MOV %04X  ",pc);
179.2224 +                        fetchea();
179.2225 +//                        if (output) printf("%04X %02X\n",pc,rmdat);
179.2226 +                        switch (rmdat&0x38)
179.2227 +                        {
179.2228 +                                case 0x00: /*ES*/
179.2229 +                                tempw=geteaw();
179.2230 +                                loadseg(tempw,&_es);
179.2231 +                                break;
179.2232 +                                case 0x08: /*CS - 8088/8086 only*/
179.2233 +                                tempw=geteaw();
179.2234 +                                loadseg(tempw,&_cs);
179.2235 +                                break;
179.2236 +                                case 0x18: /*DS*/
179.2237 +                                tempw=geteaw();
179.2238 +                                loadseg(tempw,&_ds);
179.2239 +                                if (ssegs) oldds=ds;
179.2240 +                                break;
179.2241 +                                case 0x10: /*SS*/
179.2242 +                                tempw=geteaw();
179.2243 +                                loadseg(tempw,&_ss);
179.2244 +                                if (ssegs) oldss=ss;
179.2245 +//                                printf("LOAD SS %04X %04X\n",tempw,SS);
179.2246 +//				printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4);
179.2247 +                                break;
179.2248 +                        }
179.2249 +                        cycles-=((mod==3)?2:12);
179.2250 +                                skipnextprint=1;
179.2251 +				noint=1;
179.2252 +                        break;
179.2253 +
179.2254 +                        case 0x8F: /*POPW*/
179.2255 +                        fetchea();
179.2256 +                        if (ssegs) ss=oldss;
179.2257 +                        tempw=readmemw(ss,SP);
179.2258 +                        SP+=2;
179.2259 +                        seteaw(tempw);
179.2260 +                        cycles-=25;
179.2261 +                        break;
179.2262 +
179.2263 +                        case 0x90: /*NOP*/
179.2264 +                        cycles-=3;
179.2265 +                        break;
179.2266 +
179.2267 +                        case 0x91: case 0x92: case 0x93: /*XCHG AX*/
179.2268 +                        case 0x94: case 0x95: case 0x96: case 0x97:
179.2269 +                        tempw=AX;
179.2270 +                        AX=regs[opcode&7].w;
179.2271 +                        regs[opcode&7].w=tempw;
179.2272 +                        cycles-=3;
179.2273 +                        break;
179.2274 +
179.2275 +                        case 0x98: /*CBW*/
179.2276 +                        AH=(AL&0x80)?0xFF:0;
179.2277 +                        cycles-=2;
179.2278 +                        break;
179.2279 +                        case 0x99: /*CWD*/
179.2280 +                        DX=(AX&0x8000)?0xFFFF:0;
179.2281 +                        cycles-=5;
179.2282 +                        break;
179.2283 +                        case 0x9A: /*CALL FAR*/
179.2284 +                        tempw=getword();
179.2285 +                        tempw2=getword();
179.2286 +                        tempw3=CS;
179.2287 +                        tempw4=pc;
179.2288 +                        if (ssegs) ss=oldss;
179.2289 +                        pc=tempw;
179.2290 +//                        printf("0x9a");
179.2291 +                        loadcs(tempw2);
179.2292 +                        writememw(ss,(SP-2)&0xFFFF,tempw3);
179.2293 +                        writememw(ss,(SP-4)&0xFFFF,tempw4);
179.2294 +                        SP-=4;
179.2295 +                        cycles-=36;
179.2296 +                        FETCHCLEAR();
179.2297 +                        break;
179.2298 +                        case 0x9B: /*WAIT*/
179.2299 +                        cycles-=4;
179.2300 +                        break;
179.2301 +                        case 0x9C: /*PUSHF*/
179.2302 +                        if (ssegs) ss=oldss;
179.2303 +                        writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
179.2304 +                        SP-=2;
179.2305 +                        cycles-=14;
179.2306 +                        break;
179.2307 +                        case 0x9D: /*POPF*/
179.2308 +                        if (ssegs) ss=oldss;
179.2309 +                        flags=readmemw(ss,SP)&0xFFF;
179.2310 +                        SP+=2;
179.2311 +                        cycles-=12;
179.2312 +                        break;
179.2313 +                        case 0x9E: /*SAHF*/
179.2314 +                        flags=(flags&0xFF00)|AH;
179.2315 +                        cycles-=4;
179.2316 +                        break;
179.2317 +                        case 0x9F: /*LAHF*/
179.2318 +                        AH=flags&0xFF;
179.2319 +                        cycles-=4;
179.2320 +                        break;
179.2321 +
179.2322 +                        case 0xA0: /*MOV AL,(w)*/
179.2323 +                        addr=getword();
179.2324 +                        AL=readmemb(ds+addr);
179.2325 +                        cycles-=14;
179.2326 +                        break;
179.2327 +                        case 0xA1: /*MOV AX,(w)*/
179.2328 +                        addr=getword();
179.2329 +//                        printf("Reading AX from %05X %04X:%04X\n",ds+addr,ds>>4,addr);
179.2330 +                        AX=readmemw(ds,addr);
179.2331 +                        cycles-=!4;
179.2332 +                        break;
179.2333 +                        case 0xA2: /*MOV (w),AL*/
179.2334 +                        addr=getword();
179.2335 +                        writememb(ds+addr,AL);
179.2336 +                        cycles-=14;
179.2337 +                        break;
179.2338 +                        case 0xA3: /*MOV (w),AX*/
179.2339 +                        addr=getword();
179.2340 +//                        if (!addr) printf("Write !addr %04X:%04X\n",cs>>4,pc);
179.2341 +                        writememw(ds,addr,AX);
179.2342 +                        cycles-=14;
179.2343 +                        break;
179.2344 +
179.2345 +                        case 0xA4: /*MOVSB*/
179.2346 +                        temp=readmemb(ds+SI);
179.2347 +                        writememb(es+DI,temp);
179.2348 +                        if (flags&D_FLAG) { DI--; SI--; }
179.2349 +                        else              { DI++; SI++; }
179.2350 +                        cycles-=18;
179.2351 +                        break;
179.2352 +                        case 0xA5: /*MOVSW*/
179.2353 +                        tempw=readmemw(ds,SI);
179.2354 +                        writememw(es,DI,tempw);
179.2355 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
179.2356 +                        else              { DI+=2; SI+=2; }
179.2357 +                        cycles-=18;
179.2358 +                        break;
179.2359 +                        case 0xA6: /*CMPSB*/
179.2360 +                        temp =readmemb(ds+SI);
179.2361 +                        temp2=readmemb(es+DI);
179.2362 +                        setsub8(temp,temp2);
179.2363 +                        if (flags&D_FLAG) { DI--; SI--; }
179.2364 +                        else              { DI++; SI++; }
179.2365 +                        cycles-=30;
179.2366 +                        break;
179.2367 +                        case 0xA7: /*CMPSW*/
179.2368 +                        tempw =readmemw(ds,SI);
179.2369 +                        tempw2=readmemw(es,DI);
179.2370 +//                        printf("CMPSW %04X %04X\n",tempw,tempw2);
179.2371 +                        setsub16(tempw,tempw2);
179.2372 +                        if (flags&D_FLAG) { DI-=2; SI-=2; }
179.2373 +                        else              { DI+=2; SI+=2; }
179.2374 +                        cycles-=30;
179.2375 +                        break;
179.2376 +                        case 0xA8: /*TEST AL,#8*/
179.2377 +                        temp=FETCH();
179.2378 +                        setznp8(AL&temp);
179.2379 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2380 +                        cycles-=5;
179.2381 +                        break;
179.2382 +                        case 0xA9: /*TEST AX,#16*/
179.2383 +                        tempw=getword();
179.2384 +                        setznp16(AX&tempw);
179.2385 +                        flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.2386 +                        cycles-=5;
179.2387 +                        break;
179.2388 +                        case 0xAA: /*STOSB*/
179.2389 +                        writememb(es+DI,AL);
179.2390 +                        if (flags&D_FLAG) DI--;
179.2391 +                        else              DI++;
179.2392 +                        cycles-=11;
179.2393 +                        break;
179.2394 +                        case 0xAB: /*STOSW*/
179.2395 +                        writememw(es,DI,AX);
179.2396 +                        if (flags&D_FLAG) DI-=2;
179.2397 +                        else              DI+=2;
179.2398 +                        cycles-=11;
179.2399 +                        break;
179.2400 +                        case 0xAC: /*LODSB*/
179.2401 +                        AL=readmemb(ds+SI);
179.2402 +//                        printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI);
179.2403 +                        if (flags&D_FLAG) SI--;
179.2404 +                        else              SI++;
179.2405 +                        cycles-=16;
179.2406 +                        break;
179.2407 +                        case 0xAD: /*LODSW*/
179.2408 +//                        if (times) printf("LODSW %04X:%04X\n",cs>>4,pc);
179.2409 +                        AX=readmemw(ds,SI);
179.2410 +                        if (flags&D_FLAG) SI-=2;
179.2411 +                        else              SI+=2;
179.2412 +                        cycles-=16;
179.2413 +                        break;
179.2414 +                        case 0xAE: /*SCASB*/
179.2415 +                        temp=readmemb(es+DI);
179.2416 +                        setsub8(AL,temp);
179.2417 +                        if (flags&D_FLAG) DI--;
179.2418 +                        else              DI++;
179.2419 +                        cycles-=19;
179.2420 +                        break;
179.2421 +                        case 0xAF: /*SCASW*/
179.2422 +                        tempw=readmemw(es,DI);
179.2423 +                        setsub16(AX,tempw);
179.2424 +                        if (flags&D_FLAG) DI-=2;
179.2425 +                        else              DI+=2;
179.2426 +                        cycles-=19;
179.2427 +                        break;
179.2428 +
179.2429 +                        case 0xB0: /*MOV AL,#8*/
179.2430 +                        AL=FETCH();
179.2431 +                        cycles-=4;
179.2432 +                        break;
179.2433 +                        case 0xB1: /*MOV CL,#8*/
179.2434 +                        CL=FETCH();
179.2435 +                        cycles-=4;
179.2436 +                        break;
179.2437 +                        case 0xB2: /*MOV DL,#8*/
179.2438 +                        DL=FETCH();
179.2439 +                        cycles-=4;
179.2440 +                        break;
179.2441 +                        case 0xB3: /*MOV BL,#8*/
179.2442 +                        BL=FETCH();
179.2443 +                        cycles-=4;
179.2444 +                        break;
179.2445 +                        case 0xB4: /*MOV AH,#8*/
179.2446 +                        AH=FETCH();
179.2447 +                        cycles-=4;
179.2448 +                        break;
179.2449 +                        case 0xB5: /*MOV CH,#8*/
179.2450 +                        CH=FETCH();
179.2451 +                        cycles-=4;
179.2452 +                        break;
179.2453 +                        case 0xB6: /*MOV DH,#8*/
179.2454 +                        DH=FETCH();
179.2455 +                        cycles-=4;
179.2456 +                        break;
179.2457 +                        case 0xB7: /*MOV BH,#8*/
179.2458 +                        BH=FETCH();
179.2459 +                        cycles-=4;
179.2460 +                        break;
179.2461 +                        case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/
179.2462 +                        case 0xBC: case 0xBD: case 0xBE: case 0xBF:
179.2463 +                        regs[opcode&7].w=getword();
179.2464 +                        cycles-=4;
179.2465 +                        break;
179.2466 +
179.2467 +                        case 0xC2: /*RET*/
179.2468 +                        tempw=getword();
179.2469 +                        if (ssegs) ss=oldss;
179.2470 +                        pc=readmemw(ss,SP);
179.2471 +//                        printf("C2\n");
179.2472 +//                        printf("RET to %04X\n",pc);
179.2473 +                        SP+=2+tempw;
179.2474 +                        cycles-=24;
179.2475 +                        FETCHCLEAR();
179.2476 +                        break;
179.2477 +                        case 0xC3: /*RET*/
179.2478 +                        if (ssegs) ss=oldss;
179.2479 +                        pc=readmemw(ss,SP);
179.2480 +//                        printf("C3\n");
179.2481 +//                        if (output) printf("RET to %04X %05X\n",pc,ss+SP);
179.2482 +                        SP+=2;
179.2483 +                        cycles-=20;
179.2484 +                        FETCHCLEAR();
179.2485 +                        break;
179.2486 +                        case 0xC4: /*LES*/
179.2487 +                        fetchea();
179.2488 +                        regs[reg].w=readmemw(easeg,eaaddr); //geteaw();
179.2489 +                        tempw=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
179.2490 +                        loadseg(tempw,&_es);
179.2491 +                        cycles-=24;
179.2492 +                        break;
179.2493 +                        case 0xC5: /*LDS*/
179.2494 +                        fetchea();
179.2495 +                        regs[reg].w=readmemw(easeg,eaaddr);
179.2496 +                        tempw=readmemw(easeg,(eaaddr+2)&0xFFFF);
179.2497 +                        loadseg(tempw,&_ds);
179.2498 +                        if (ssegs) oldds=ds;
179.2499 +                        cycles-=24;
179.2500 +                        break;
179.2501 +                        case 0xC6: /*MOV b,#8*/
179.2502 +                        fetchea();
179.2503 +                        temp=FETCH();
179.2504 +                        seteab(temp);
179.2505 +                        cycles-=((mod==3)?4:14);
179.2506 +                        break;
179.2507 +                        case 0xC7: /*MOV w,#16*/
179.2508 +                        fetchea();
179.2509 +                        tempw=getword();
179.2510 +                        seteaw(tempw);
179.2511 +                        cycles-=((mod==3)?4:14);
179.2512 +                        break;
179.2513 +
179.2514 +                        case 0xCA: /*RETF*/
179.2515 +                        tempw=getword();
179.2516 +                        if (ssegs) ss=oldss;
179.2517 +                        pc=readmemw(ss,SP);
179.2518 +//                        printf("CA\n");
179.2519 +                        loadcs(readmemw(ss,SP+2));
179.2520 +                        SP+=4;
179.2521 +                        SP+=tempw;
179.2522 +                        cycles-=33;
179.2523 +                        FETCHCLEAR();
179.2524 +                        break;
179.2525 +                        case 0xCB: /*RETF*/
179.2526 +                        if (ssegs) ss=oldss;
179.2527 +                        pc=readmemw(ss,SP);
179.2528 +//                        printf("CB\n");
179.2529 +                        loadcs(readmemw(ss,SP+2));
179.2530 +                        SP+=4;
179.2531 +                        cycles-=34;
179.2532 +                        FETCHCLEAR();
179.2533 +                        break;
179.2534 +                        case 0xCC: /*INT 3*/
179.2535 +                        if (ssegs) ss=oldss;
179.2536 +                        writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
179.2537 +                        writememw(ss,((SP-4)&0xFFFF),CS);
179.2538 +                        writememw(ss,((SP-6)&0xFFFF),pc);
179.2539 +                        SP-=6;
179.2540 +                        addr=3<<2;
179.2541 +                        flags&=~I_FLAG;
179.2542 +                        flags&=~T_FLAG;
179.2543 +//                        printf("CC %04X:%04X  ",CS,pc);
179.2544 +                        pc=readmemw(0,addr);
179.2545 +                        loadcs(readmemw(0,addr+2));
179.2546 +                        FETCHCLEAR();
179.2547 +//                        printf("%04X:%04X\n",CS,pc);
179.2548 +                        cycles-=72;
179.2549 +                        break;
179.2550 +                        case 0xCD: /*INT*/
179.2551 +                        lastpc=pc;
179.2552 +                        lastcs=CS;
179.2553 +                        temp=FETCH();
179.2554 +                        
179.2555 +//                        if (temp == 0x13  && AX == 0x0201  && ES == 0x0BF5 && CX == 0x1D06) output = 3;
179.2556 +//                        if (temp==0x10 && !AH) printf("Entering mode %02X\n",AL);
179.2557 +//                        if (temp==0x18 || temp==0x19) { printf("INT %02X\n",temp); output=1; }
179.2558 +//                        /*if (temp==0x13) */printf("INT %02X %04X %04X:%04X %04X %04X:%04X %04X:%04X\n",temp,AX,ES,BX,CX,DS,DX,CS,pc);
179.2559 +                        //if (temp == 0x13 && AH == 2) output = 3;
179.2560 +/*                        if (CS==0xC800 && temp==0x13)
179.2561 +                        {
179.2562 +                                output=3;
179.2563 +                                timetolive=100000;
179.2564 +                        }*/
179.2565 +/*                        if (temp==0x10) printf("INT 10 %04X %04X %04X %04X %04X:%04X %06X %06X %c\n",AX,BX,CX,DX,cs>>4,pc,ds,ds+DX, (AL > 31) ? AL : '.');
179.2566 +                        if (temp == 0x10 && AX == 0xe35)
179.2567 +                        {
179.2568 +                                dumpregs();
179.2569 +
179.2570 +                        }*/
179.2571 +/*                        if (temp==0x21 && AH==9)
179.2572 +                        {
179.2573 +                                addr=0;
179.2574 +                                while (ram[ds+DX+addr]!='$')
179.2575 +                                {
179.2576 +                                        printf("%c",ram[ds+DX+addr]);
179.2577 +                                        addr++;
179.2578 +                                }
179.2579 +                                printf("\n");
179.2580 +                                printf("Called from %04X\n",readmemw(ss,SP));
179.2581 +                        }*/
179.2582 +//                        output=0;
179.2583 +//                        if (temp==0x13 && AH==3) printf("Write sector %04X:%04X %05X\n",es>>4,BX,es+BX);
179.2584 +/*                        if (temp==0x13 && (DL==0x80 || DL==0x81) && AH>0)
179.2585 +                        {
179.2586 +                                int13hdc();
179.2587 +                        }
179.2588 +                        else *//*if (temp==0x13 && AH==2 && DL<2)// && FASTDISC)
179.2589 +                        {
179.2590 +                                int13read();
179.2591 +                                //output=1;
179.2592 +                        }
179.2593 +                        else if (temp==0x13 && AH==3 && DL<2)// && FASTDISC)
179.2594 +                        {
179.2595 +                                int13write();
179.2596 +                        }
179.2597 +                        else if (temp==0x13 && AH==4 && DL<2)// && FASTDISC)
179.2598 +                        {
179.2599 +                                AH=0;
179.2600 +                                flags&=~C_FLAG;
179.2601 +                        }
179.2602 +                        else
179.2603 +                        {*/
179.2604 +                                if (ssegs) ss=oldss;
179.2605 +                                writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
179.2606 +                                writememw(ss,((SP-4)&0xFFFF),CS);
179.2607 +                                writememw(ss,((SP-6)&0xFFFF),pc);
179.2608 +                                flags&=~T_FLAG;
179.2609 +                                SP-=6;
179.2610 +                                addr=temp<<2;
179.2611 +                                pc=readmemw(0,addr);
179.2612 +//                        printf("CD\n");
179.2613 +                                loadcs(readmemw(0,addr+2));
179.2614 +                                FETCHCLEAR();
179.2615 +//                        }
179.2616 +                        cycles-=71;
179.2617 +                        break;
179.2618 +                        case 0xCF: /*IRET*/
179.2619 +                        if (ssegs) ss=oldss;
179.2620 +                        tempw=CS;
179.2621 +                        tempw2=pc;
179.2622 +                        inint=0;
179.2623 +                        pc=readmemw(ss,SP);
179.2624 +//                        printf("CF\n");
179.2625 +                        loadcs(readmemw(ss,((SP+2)&0xFFFF)));
179.2626 +                        flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF;
179.2627 +                        SP+=6;
179.2628 +                        cycles-=44;
179.2629 +                        FETCHCLEAR();
179.2630 +                        break;
179.2631 +                        case 0xD0:
179.2632 +                        fetchea();
179.2633 +                        temp=geteab();
179.2634 +                        switch (rmdat&0x38)
179.2635 +                        {
179.2636 +                                case 0x00: /*ROL b,1*/
179.2637 +                                if (temp&0x80) flags|=C_FLAG;
179.2638 +                                else           flags&=~C_FLAG;
179.2639 +                                temp<<=1;
179.2640 +                                if (flags&C_FLAG) temp|=1;
179.2641 +                                seteab(temp);
179.2642 +//                                setznp8(temp);
179.2643 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
179.2644 +                                else                          flags&=~V_FLAG;
179.2645 +                                cycles-=((mod==3)?2:23);
179.2646 +                                break;
179.2647 +                                case 0x08: /*ROR b,1*/
179.2648 +                                if (temp&1) flags|=C_FLAG;
179.2649 +                                else        flags&=~C_FLAG;
179.2650 +                                temp>>=1;
179.2651 +                                if (flags&C_FLAG) temp|=0x80;
179.2652 +                                seteab(temp);
179.2653 +//                                setznp8(temp);
179.2654 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
179.2655 +                                else                       flags&=~V_FLAG;
179.2656 +                                cycles-=((mod==3)?2:23);
179.2657 +                                break;
179.2658 +                                case 0x10: /*RCL b,1*/
179.2659 +                                temp2=flags&C_FLAG;
179.2660 +                                if (temp&0x80) flags|=C_FLAG;
179.2661 +                                else           flags&=~C_FLAG;
179.2662 +                                temp<<=1;
179.2663 +                                if (temp2) temp|=1;
179.2664 +                                seteab(temp);
179.2665 +//                                setznp8(temp);
179.2666 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
179.2667 +                                else                          flags&=~V_FLAG;
179.2668 +                                cycles-=((mod==3)?2:23);
179.2669 +                                break;
179.2670 +                                case 0x18: /*RCR b,1*/
179.2671 +                                temp2=flags&C_FLAG;
179.2672 +                                if (temp&1) flags|=C_FLAG;
179.2673 +                                else        flags&=~C_FLAG;
179.2674 +                                temp>>=1;
179.2675 +                                if (temp2) temp|=0x80;
179.2676 +                                seteab(temp);
179.2677 +//                                setznp8(temp);
179.2678 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
179.2679 +                                else                       flags&=~V_FLAG;
179.2680 +                                cycles-=((mod==3)?2:23);
179.2681 +                                break;
179.2682 +                                case 0x20: case 0x30: /*SHL b,1*/
179.2683 +                                if (temp&0x80) flags|=C_FLAG;
179.2684 +                                else           flags&=~C_FLAG;
179.2685 +                                if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
179.2686 +                                else                       flags&=~V_FLAG;
179.2687 +                                temp<<=1;
179.2688 +                                seteab(temp);
179.2689 +                                setznp8(temp);
179.2690 +                                cycles-=((mod==3)?2:23);
179.2691 +                                flags|=A_FLAG;
179.2692 +                                break;
179.2693 +                                case 0x28: /*SHR b,1*/
179.2694 +                                if (temp&1) flags|=C_FLAG;
179.2695 +                                else        flags&=~C_FLAG;
179.2696 +                                if (temp&0x80) flags|=V_FLAG;
179.2697 +                                else           flags&=~V_FLAG;
179.2698 +                                temp>>=1;
179.2699 +                                seteab(temp);
179.2700 +                                setznp8(temp);
179.2701 +                                cycles-=((mod==3)?2:23);
179.2702 +                                flags|=A_FLAG;
179.2703 +                                break;
179.2704 +                                case 0x38: /*SAR b,1*/
179.2705 +                                if (temp&1) flags|=C_FLAG;
179.2706 +                                else        flags&=~C_FLAG;
179.2707 +                                temp>>=1;
179.2708 +                                if (temp&0x40) temp|=0x80;
179.2709 +                                seteab(temp);
179.2710 +                                setznp8(temp);
179.2711 +                                cycles-=((mod==3)?2:23);
179.2712 +                                flags|=A_FLAG;
179.2713 +                                flags&=~V_FLAG;
179.2714 +                                break;
179.2715 +
179.2716 +//                                default:
179.2717 +//                                printf("Bad D0 opcode %02X\n",rmdat&0x38);
179.2718 +//                                dumpregs();
179.2719 +//                                exit(-1);
179.2720 +                        }
179.2721 +                        break;
179.2722 +
179.2723 +                        case 0xD1:
179.2724 +                        fetchea();
179.2725 +                        tempw=geteaw();
179.2726 +                        switch (rmdat&0x38)
179.2727 +                        {
179.2728 +                                case 0x00: /*ROL w,1*/
179.2729 +                                if (tempw&0x8000) flags|=C_FLAG;
179.2730 +                                else              flags&=~C_FLAG;
179.2731 +                                tempw<<=1;
179.2732 +                                if (flags&C_FLAG) tempw|=1;
179.2733 +                                seteaw(tempw);
179.2734 +//                                setznp16(tempw);
179.2735 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
179.2736 +                                else                            flags&=~V_FLAG;
179.2737 +                                cycles-=((mod==3)?2:23);
179.2738 +                                break;
179.2739 +                                case 0x08: /*ROR w,1*/
179.2740 +                                if (tempw&1) flags|=C_FLAG;
179.2741 +                                else         flags&=~C_FLAG;
179.2742 +                                tempw>>=1;
179.2743 +                                if (flags&C_FLAG) tempw|=0x8000;
179.2744 +                                seteaw(tempw);
179.2745 +//                                setznp16(tempw);
179.2746 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
179.2747 +                                else                           flags&=~V_FLAG;
179.2748 +                                cycles-=((mod==3)?2:23);
179.2749 +                                break;
179.2750 +                                case 0x10: /*RCL w,1*/
179.2751 +                                temp2=flags&C_FLAG;
179.2752 +                                if (tempw&0x8000) flags|=C_FLAG;
179.2753 +                                else              flags&=~C_FLAG;
179.2754 +                                tempw<<=1;
179.2755 +                                if (temp2) tempw|=1;
179.2756 +                                seteaw(tempw);
179.2757 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
179.2758 +                                else                            flags&=~V_FLAG;
179.2759 +                                cycles-=((mod==3)?2:23);
179.2760 +                                break;
179.2761 +                                case 0x18: /*RCR w,1*/
179.2762 +                                temp2=flags&C_FLAG;
179.2763 +                                if (tempw&1) flags|=C_FLAG;
179.2764 +                                else         flags&=~C_FLAG;
179.2765 +                                tempw>>=1;
179.2766 +                                if (temp2) tempw|=0x8000;
179.2767 +                                seteaw(tempw);
179.2768 +//                                setznp16(tempw);
179.2769 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
179.2770 +                                else                           flags&=~V_FLAG;
179.2771 +                                cycles-=((mod==3)?2:23);
179.2772 +                                break;
179.2773 +                                case 0x20: case 0x30: /*SHL w,1*/
179.2774 +                                if (tempw&0x8000) flags|=C_FLAG;
179.2775 +                                else              flags&=~C_FLAG;
179.2776 +                                if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
179.2777 +                                else                           flags&=~V_FLAG;
179.2778 +                                tempw<<=1;
179.2779 +                                seteaw(tempw);
179.2780 +                                setznp16(tempw);
179.2781 +                                cycles-=((mod==3)?2:23);
179.2782 +                                flags|=A_FLAG;
179.2783 +                                break;
179.2784 +                                case 0x28: /*SHR w,1*/
179.2785 +                                if (tempw&1) flags|=C_FLAG;
179.2786 +                                else         flags&=~C_FLAG;
179.2787 +                                if (tempw&0x8000) flags|=V_FLAG;
179.2788 +                                else              flags&=~V_FLAG;
179.2789 +                                tempw>>=1;
179.2790 +                                seteaw(tempw);
179.2791 +                                setznp16(tempw);
179.2792 +                                cycles-=((mod==3)?2:23);
179.2793 +                                flags|=A_FLAG;
179.2794 +                                break;
179.2795 +
179.2796 +                                case 0x38: /*SAR w,1*/
179.2797 +                                if (tempw&1) flags|=C_FLAG;
179.2798 +                                else         flags&=~C_FLAG;
179.2799 +                                tempw>>=1;
179.2800 +                                if (tempw&0x4000) tempw|=0x8000;
179.2801 +                                seteaw(tempw);
179.2802 +                                setznp16(tempw);
179.2803 +                                cycles-=((mod==3)?2:23);
179.2804 +                                flags|=A_FLAG;
179.2805 +                                flags&=~V_FLAG;
179.2806 +                                break;
179.2807 +
179.2808 +//                                default:
179.2809 +//                                printf("Bad D1 opcode %02X\n",rmdat&0x38);
179.2810 +//                                dumpregs();
179.2811 +//                                exit(-1);
179.2812 +                        }
179.2813 +                        break;
179.2814 +
179.2815 +                        case 0xD2:
179.2816 +                        fetchea();
179.2817 +                        temp=geteab();
179.2818 +                        c=CL;
179.2819 +//                        cycles-=c;
179.2820 +                        if (!c) break;
179.2821 +//                        if (c>7) printf("Shiftb %i %02X\n",rmdat&0x38,c);
179.2822 +                        switch (rmdat&0x38)
179.2823 +                        {
179.2824 +                                case 0x00: /*ROL b,CL*/
179.2825 +                                while (c>0)
179.2826 +                                {
179.2827 +                                        temp2=(temp&0x80)?1:0;
179.2828 +                                        temp=(temp<<1)|temp2;
179.2829 +                                        c--;
179.2830 +                                        cycles-=4;
179.2831 +                                }
179.2832 +                                if (temp2) flags|=C_FLAG;
179.2833 +                                else       flags&=~C_FLAG;
179.2834 +                                seteab(temp);
179.2835 +//                                setznp8(temp);
179.2836 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
179.2837 +                                else                          flags&=~V_FLAG;
179.2838 +                                cycles-=((mod==3)?8:28);
179.2839 +                                break;
179.2840 +                                case 0x08: /*ROR b,CL*/
179.2841 +                                while (c>0)
179.2842 +                                {
179.2843 +                                        temp2=temp&1;
179.2844 +                                        temp>>=1;
179.2845 +                                        if (temp2) temp|=0x80;
179.2846 +                                        c--;
179.2847 +                                        cycles-=4;
179.2848 +                                }
179.2849 +                                if (temp2) flags|=C_FLAG;
179.2850 +                                else       flags&=~C_FLAG;
179.2851 +                                seteab(temp);
179.2852 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
179.2853 +                                else                       flags&=~V_FLAG;
179.2854 +                                cycles-=((mod==3)?8:28);
179.2855 +                                break;
179.2856 +                                case 0x10: /*RCL b,CL*/
179.2857 +//                                printf("RCL %i %02X %02X\n",c,CL,temp);
179.2858 +                                while (c>0)
179.2859 +                                {
179.2860 +                                        templ=flags&C_FLAG;
179.2861 +                                        temp2=temp&0x80;
179.2862 +                                        temp<<=1;
179.2863 +                                        if (temp2) flags|=C_FLAG;
179.2864 +                                        else       flags&=~C_FLAG;
179.2865 +                                        if (templ) temp|=1;
179.2866 +                                        c--;
179.2867 +                                        cycles-=4;
179.2868 +                                }
179.2869 +//                                printf("Now %02X\n",temp);
179.2870 +                                seteab(temp);
179.2871 +                                if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
179.2872 +                                else                          flags&=~V_FLAG;
179.2873 +                                cycles-=((mod==3)?8:28);
179.2874 +                                break;
179.2875 +                                case 0x18: /*RCR b,CL*/
179.2876 +                                while (c>0)
179.2877 +                                {
179.2878 +                                        templ=flags&C_FLAG;
179.2879 +                                        temp2=temp&1;
179.2880 +                                        temp>>=1;
179.2881 +                                        if (temp2) flags|=C_FLAG;
179.2882 +                                        else       flags&=~C_FLAG;
179.2883 +                                        if (templ) temp|=0x80;
179.2884 +                                        c--;
179.2885 +                                        cycles-=4;
179.2886 +                                }
179.2887 +//                                if (temp2) flags|=C_FLAG;
179.2888 +//                                else       flags&=~C_FLAG;
179.2889 +                                seteab(temp);
179.2890 +                                if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
179.2891 +                                else                       flags&=~V_FLAG;
179.2892 +                                cycles-=((mod==3)?8:28);
179.2893 +                                break;
179.2894 +                                case 0x20: case 0x30: /*SHL b,CL*/
179.2895 +                                if ((temp<<(c-1))&0x80) flags|=C_FLAG;
179.2896 +                                else                    flags&=~C_FLAG;
179.2897 +                                temp<<=c;
179.2898 +                                seteab(temp);
179.2899 +                                setznp8(temp);
179.2900 +                                cycles-=(c*4);
179.2901 +                                cycles-=((mod==3)?8:28);
179.2902 +                                flags|=A_FLAG;
179.2903 +                                break;
179.2904 +                                case 0x28: /*SHR b,CL*/
179.2905 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
179.2906 +                                else                 flags&=~C_FLAG;
179.2907 +                                temp>>=c;
179.2908 +                                seteab(temp);
179.2909 +                                setznp8(temp);
179.2910 +                                cycles-=(c*4);
179.2911 +                                cycles-=((mod==3)?8:28);
179.2912 +                                flags|=A_FLAG;
179.2913 +                                break;
179.2914 +                                case 0x38: /*SAR b,CL*/
179.2915 +                                if ((temp>>(c-1))&1) flags|=C_FLAG;
179.2916 +                                else                 flags&=~C_FLAG;
179.2917 +                                while (c>0)
179.2918 +                                {
179.2919 +                                        temp>>=1;
179.2920 +                                        if (temp&0x40) temp|=0x80;
179.2921 +                                        c--;
179.2922 +                                        cycles-=4;
179.2923 +                                }
179.2924 +                                seteab(temp);
179.2925 +                                setznp8(temp);
179.2926 +                                cycles-=((mod==3)?8:28);
179.2927 +                                flags|=A_FLAG;
179.2928 +                                break;
179.2929 +
179.2930 +//                                default:
179.2931 +//                                printf("Bad D2 opcode %02X\n",rmdat&0x38);
179.2932 +//                                dumpregs();
179.2933 +//                                exit(-1);
179.2934 +                        }
179.2935 +                        break;
179.2936 +
179.2937 +                        case 0xD3:
179.2938 +                        fetchea();
179.2939 +                        tempw=geteaw();
179.2940 +                        c=CL;
179.2941 +//                      cycles-=c;
179.2942 +                        if (!c) break;
179.2943 +//                        if (c>15) printf("Shiftw %i %02X\n",rmdat&0x38,c);
179.2944 +                        switch (rmdat&0x38)
179.2945 +                        {
179.2946 +                                case 0x00: /*ROL w,CL*/
179.2947 +                                while (c>0)
179.2948 +                                {
179.2949 +                                        temp=(tempw&0x8000)?1:0;
179.2950 +                                        tempw=(tempw<<1)|temp;
179.2951 +                                        c--;
179.2952 +                                        cycles-=4;
179.2953 +                                }
179.2954 +                                if (temp) flags|=C_FLAG;
179.2955 +                                else      flags&=~C_FLAG;
179.2956 +                                seteaw(tempw);
179.2957 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
179.2958 +                                else                            flags&=~V_FLAG;
179.2959 +                                cycles-=((mod==3)?8:28);
179.2960 +                                break;
179.2961 +                                case 0x08: /*ROR w,CL*/
179.2962 +                                while (c>0)
179.2963 +                                {
179.2964 +                                        tempw2=(tempw&1)?0x8000:0;
179.2965 +                                        tempw=(tempw>>1)|tempw2;
179.2966 +                                        c--;
179.2967 +                                        cycles-=4;
179.2968 +                                }
179.2969 +                                if (tempw2) flags|=C_FLAG;
179.2970 +                                else        flags&=~C_FLAG;
179.2971 +                                seteaw(tempw);
179.2972 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
179.2973 +                                else                           flags&=~V_FLAG;
179.2974 +                                cycles-=((mod==3)?8:28);
179.2975 +                                break;
179.2976 +                                case 0x10: /*RCL w,CL*/
179.2977 +                                while (c>0)
179.2978 +                                {
179.2979 +                                        templ=flags&C_FLAG;
179.2980 +                                        if (tempw&0x8000) flags|=C_FLAG;
179.2981 +                                        else              flags&=~C_FLAG;
179.2982 +                                        tempw=(tempw<<1)|templ;
179.2983 +                                        c--;
179.2984 +                                        cycles-=4;
179.2985 +                                }
179.2986 +                                if (temp) flags|=C_FLAG;
179.2987 +                                else      flags&=~C_FLAG;
179.2988 +                                seteaw(tempw);
179.2989 +                                if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
179.2990 +                                else                            flags&=~V_FLAG;
179.2991 +                                cycles-=((mod==3)?8:28);
179.2992 +                                break;
179.2993 +                                case 0x18: /*RCR w,CL*/
179.2994 +                                while (c>0)
179.2995 +                                {
179.2996 +                                        templ=flags&C_FLAG;
179.2997 +                                        tempw2=(templ&1)?0x8000:0;
179.2998 +                                        if (tempw&1) flags|=C_FLAG;
179.2999 +                                        else         flags&=~C_FLAG;
179.3000 +                                        tempw=(tempw>>1)|tempw2;
179.3001 +                                        c--;
179.3002 +                                        cycles-=4;
179.3003 +                                }
179.3004 +                                if (tempw2) flags|=C_FLAG;
179.3005 +                                else        flags&=~C_FLAG;
179.3006 +                                seteaw(tempw);
179.3007 +                                if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
179.3008 +                                else                           flags&=~V_FLAG;
179.3009 +                                cycles-=((mod==3)?8:28);
179.3010 +                                break;
179.3011 +
179.3012 +                                case 0x20: case 0x30: /*SHL w,CL*/
179.3013 +                                if (c>16)
179.3014 +                                {
179.3015 +                                        tempw=0;
179.3016 +                                        flags&=~C_FLAG;
179.3017 +                                }
179.3018 +                                else
179.3019 +                                {
179.3020 +                                        if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
179.3021 +                                        else                       flags&=~C_FLAG;
179.3022 +                                        tempw<<=c;
179.3023 +                                }
179.3024 +                                seteaw(tempw);
179.3025 +                                setznp16(tempw);
179.3026 +                                cycles-=(c*4);
179.3027 +                                cycles-=((mod==3)?8:28);
179.3028 +                                flags|=A_FLAG;
179.3029 +                                break;
179.3030 +
179.3031 +                                case 0x28:            /*SHR w,CL*/
179.3032 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
179.3033 +                                else                  flags&=~C_FLAG;
179.3034 +                                tempw>>=c;
179.3035 +                                seteaw(tempw);
179.3036 +                                setznp16(tempw);
179.3037 +                                cycles-=(c*4);
179.3038 +                                cycles-=((mod==3)?8:28);
179.3039 +                                flags|=A_FLAG;
179.3040 +                                break;
179.3041 +
179.3042 +                                case 0x38:            /*SAR w,CL*/
179.3043 +                                tempw2=tempw&0x8000;
179.3044 +                                if ((tempw>>(c-1))&1) flags|=C_FLAG;
179.3045 +                                else                  flags&=~C_FLAG;
179.3046 +                                while (c>0)
179.3047 +                                {
179.3048 +                                        tempw=(tempw>>1)|tempw2;
179.3049 +                                        c--;
179.3050 +                                        cycles-=4;
179.3051 +                                }
179.3052 +                                seteaw(tempw);
179.3053 +                                setznp16(tempw);
179.3054 +                                cycles-=((mod==3)?8:28);
179.3055 +                                flags|=A_FLAG;
179.3056 +                                break;
179.3057 +
179.3058 +//                                default:
179.3059 +//                                printf("Bad D3 opcode %02X\n",rmdat&0x38);
179.3060 +//                                dumpregs();
179.3061 +//                                exit(-1);
179.3062 +                        }
179.3063 +                        break;
179.3064 +
179.3065 +                        case 0xD4: /*AAM*/
179.3066 +                        tempws=FETCH();
179.3067 +                        AH=AL/tempws;
179.3068 +                        AL%=tempws;
179.3069 +                        setznp168(AX);
179.3070 +                        cycles-=83;
179.3071 +                        break;
179.3072 +                        case 0xD5: /*AAD*/
179.3073 +                        tempws=FETCH();
179.3074 +                        AL=(AH*tempws)+AL;
179.3075 +                        AH=0;
179.3076 +                        setznp168(AX);
179.3077 +                        cycles-=60;
179.3078 +                        break;
179.3079 +                        case 0xD7: /*XLAT*/
179.3080 +                        addr=BX+AL;
179.3081 +                        AL=readmemb(ds+addr);
179.3082 +                        cycles-=11;
179.3083 +                        break;
179.3084 +                        case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/
179.3085 +                        case 0xDC: case 0xDE: case 0xDF: case 0xD8:
179.3086 +                        fetchea();
179.3087 +                        geteab();
179.3088 +                        break;
179.3089 +
179.3090 +                        case 0xE0: /*LOOPNE*/
179.3091 +                        offset=(int8_t)FETCH();
179.3092 +                        CX--;
179.3093 +                        if (CX && !(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.3094 +                        cycles-=6;
179.3095 +                        break;
179.3096 +                        case 0xE1: /*LOOPE*/
179.3097 +                        offset=(int8_t)FETCH();
179.3098 +                        CX--;
179.3099 +                        if (CX && (flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.3100 +                        cycles-=6;
179.3101 +                        break;
179.3102 +                        case 0xE2: /*LOOP*/
179.3103 +//                        printf("LOOP start\n");
179.3104 +                        offset=(int8_t)FETCH();
179.3105 +                        CX--;
179.3106 +                        if (CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.3107 +                        cycles-=5;
179.3108 +//                        printf("LOOP end!\n");
179.3109 +                        break;
179.3110 +                        case 0xE3: /*JCXZ*/
179.3111 +                        offset=(int8_t)FETCH();
179.3112 +                        if (!CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
179.3113 +                        cycles-=6;
179.3114 +                        break;
179.3115 +
179.3116 +                        case 0xE4: /*IN AL*/
179.3117 +                        temp=FETCH();
179.3118 +                        AL=inb(temp);
179.3119 +                        cycles-=14;
179.3120 +                        break;
179.3121 +                        case 0xE5: /*IN AX*/
179.3122 +                        temp=FETCH();
179.3123 +                        AL=inb(temp);
179.3124 +                        AH=inb(temp+1);
179.3125 +                        cycles-=14;
179.3126 +                        break;
179.3127 +                        case 0xE6: /*OUT AL*/
179.3128 +                        temp=FETCH();
179.3129 +                        outb(temp,AL);
179.3130 +                        cycles-=14;
179.3131 +                        break;
179.3132 +                        case 0xE7: /*OUT AX*/
179.3133 +                        temp=FETCH();
179.3134 +                        outb(temp,AL);
179.3135 +                        outb(temp+1,AH);
179.3136 +                        cycles-=14;
179.3137 +                        break;
179.3138 +
179.3139 +                        case 0xE8: /*CALL rel 16*/
179.3140 +                        tempw=getword();
179.3141 +                        if (ssegs) ss=oldss;
179.3142 +//                        writememb(ss+((SP-1)&0xFFFF),pc>>8);
179.3143 +                        writememw(ss,((SP-2)&0xFFFF),pc);
179.3144 +                        SP-=2;
179.3145 +                        pc+=tempw;
179.3146 +                        cycles-=23;
179.3147 +                        FETCHCLEAR();
179.3148 +                        break;
179.3149 +                        case 0xE9: /*JMP rel 16*/
179.3150 +//                        printf("PC was %04X\n",pc);
179.3151 +                        pc+=getword();
179.3152 +//                        printf("PC now %04X\n",pc);
179.3153 +                        cycles-=15;
179.3154 +                        FETCHCLEAR();
179.3155 +                        break;
179.3156 +                        case 0xEA: /*JMP far*/
179.3157 +                        addr=getword();
179.3158 +                        tempw=getword();
179.3159 +                        pc=addr;
179.3160 +//                        printf("EA\n");
179.3161 +                        loadcs(tempw);
179.3162 +//                        cs=loadcs(CS);
179.3163 +//                        cs=CS<<4;
179.3164 +                        cycles-=15;
179.3165 +                        FETCHCLEAR();
179.3166 +                        break;
179.3167 +                        case 0xEB: /*JMP rel*/
179.3168 +                        offset=(int8_t)FETCH();
179.3169 +                        pc+=offset;
179.3170 +                        cycles-=15;
179.3171 +                        FETCHCLEAR();
179.3172 +                        break;
179.3173 +                        case 0xEC: /*IN AL,DX*/
179.3174 +                        AL=inb(DX);
179.3175 +                        cycles-=12;
179.3176 +                        break;
179.3177 +                        case 0xED: /*IN AX,DX*/
179.3178 +                        AL=inb(DX);
179.3179 +                        AH=inb(DX+1);
179.3180 +                        cycles-=12;
179.3181 +                        break;
179.3182 +                        case 0xEE: /*OUT DX,AL*/
179.3183 +                        outb(DX,AL);
179.3184 +                        cycles-=12;
179.3185 +                        break;
179.3186 +                        case 0xEF: /*OUT DX,AX*/
179.3187 +                        outb(DX,AL);
179.3188 +                        outb(DX+1,AH);
179.3189 +                        cycles-=12;
179.3190 +                        break;
179.3191 +
179.3192 +                        case 0xF0: /*LOCK*/
179.3193 +                        cycles-=4;
179.3194 +                        break;
179.3195 +
179.3196 +                        case 0xF2: /*REPNE*/
179.3197 +                        rep(0);
179.3198 +                        break;
179.3199 +                        case 0xF3: /*REPE*/
179.3200 +                        rep(1);
179.3201 +                        break;
179.3202 +
179.3203 +                        case 0xF4: /*HLT*/
179.3204 +//                        printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83);
179.3205 +/*                        if (!(flags & I_FLAG))
179.3206 +                        {
179.3207 +                                pclog("HLT\n");
179.3208 +                                dumpregs();
179.3209 +                                exit(-1);
179.3210 +                        }*/
179.3211 +                        inhlt=1;
179.3212 +                        pc--;
179.3213 +                        FETCHCLEAR();
179.3214 +                        cycles-=2;
179.3215 +                        break;
179.3216 +                        case 0xF5: /*CMC*/
179.3217 +                        flags^=C_FLAG;
179.3218 +                        cycles-=2;
179.3219 +                        break;
179.3220 +
179.3221 +                        case 0xF6:
179.3222 +                        fetchea();
179.3223 +                        temp=geteab();
179.3224 +                        switch (rmdat&0x38)
179.3225 +                        {
179.3226 +                                case 0x00: /*TEST b,#8*/
179.3227 +                                temp2=FETCH();
179.3228 +                                temp&=temp2;
179.3229 +                                setznp8(temp);
179.3230 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.3231 +                                cycles-=((mod==3)?5:11);
179.3232 +                                break;
179.3233 +                                case 0x10: /*NOT b*/
179.3234 +                                temp=~temp;
179.3235 +                                seteab(temp);
179.3236 +                                cycles-=((mod==3)?3:24);
179.3237 +                                break;
179.3238 +                                case 0x18: /*NEG b*/
179.3239 +                                setsub8(0,temp);
179.3240 +                                temp=0-temp;
179.3241 +                                seteab(temp);
179.3242 +                                cycles-=((mod==3)?3:24);
179.3243 +                                break;
179.3244 +                                case 0x20: /*MUL AL,b*/
179.3245 +                                setznp8(AL);
179.3246 +                                AX=AL*temp;
179.3247 +                                if (AX) flags&=~Z_FLAG;
179.3248 +                                else    flags|=Z_FLAG;
179.3249 +                                if (AH) flags|=(C_FLAG|V_FLAG);
179.3250 +                                else    flags&=~(C_FLAG|V_FLAG);
179.3251 +                                cycles-=70;
179.3252 +                                break;
179.3253 +                                case 0x28: /*IMUL AL,b*/
179.3254 +                                setznp8(AL);
179.3255 +                                tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
179.3256 +                                AX=tempws&0xFFFF;
179.3257 +                                if (AX) flags&=~Z_FLAG;
179.3258 +                                else    flags|=Z_FLAG;
179.3259 +                                if (AH) flags|=(C_FLAG|V_FLAG);
179.3260 +                                else    flags&=~(C_FLAG|V_FLAG);
179.3261 +                                cycles-=80;
179.3262 +                                break;
179.3263 +                                case 0x30: /*DIV AL,b*/
179.3264 +                                tempw=AX;
179.3265 +                                if (temp)
179.3266 +                                {
179.3267 +                                        tempw2=tempw%temp;
179.3268 +/*                                        if (!tempw)
179.3269 +                                        {
179.3270 +                                                writememw((ss+SP)-2,flags|0xF000);
179.3271 +                                                writememw((ss+SP)-4,cs>>4);
179.3272 +                                                writememw((ss+SP)-6,pc);
179.3273 +                                                SP-=6;
179.3274 +                                                flags&=~I_FLAG;
179.3275 +                                                pc=readmemw(0);
179.3276 +                                                cs=readmemw(2)<<4;
179.3277 +                                                printf("Div by zero %04X:%04X\n",cs>>4,pc);
179.3278 +//                                                dumpregs();
179.3279 +//                                                exit(-1);
179.3280 +                                        }
179.3281 +                                        else
179.3282 +                                        {*/
179.3283 +                                                AH=tempw2;
179.3284 +                                                tempw/=temp;
179.3285 +                                                AL=tempw&0xFF;
179.3286 +//                                        }
179.3287 +                                }
179.3288 +                                else
179.3289 +                                {
179.3290 +                                        printf("DIVb BY 0 %04X:%04X\n",cs>>4,pc);
179.3291 +                                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3292 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
179.3293 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
179.3294 +                                        SP-=6;
179.3295 +                                        flags&=~I_FLAG;
179.3296 +                                        flags&=~T_FLAG;
179.3297 +                                        pc=readmemw(0,0);
179.3298 +//                        printf("F6 30\n");
179.3299 +                                        loadcs(readmemw(0,2));
179.3300 +                                        FETCHCLEAR();
179.3301 +//                                                cs=loadcs(CS);
179.3302 +//                                                cs=CS<<4;
179.3303 +//                                        printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30);
179.3304 +//                                        dumpregs();
179.3305 +//                                        exit(-1);
179.3306 +                                }
179.3307 +                                cycles-=80;
179.3308 +                                break;
179.3309 +                                case 0x38: /*IDIV AL,b*/
179.3310 +                                tempws=(int)AX;
179.3311 +                                if (temp)
179.3312 +                                {
179.3313 +                                        tempw2=tempws%(int)((int8_t)temp);
179.3314 +/*                                        if (!tempw)
179.3315 +                                        {
179.3316 +                                                writememw((ss+SP)-2,flags|0xF000);
179.3317 +                                                writememw((ss+SP)-4,cs>>4);
179.3318 +                                                writememw((ss+SP)-6,pc);
179.3319 +                                                SP-=6;
179.3320 +                                                flags&=~I_FLAG;
179.3321 +                                                pc=readmemw(0);
179.3322 +                                                cs=readmemw(2)<<4;
179.3323 +                                                printf("Div by zero %04X:%04X\n",cs>>4,pc);
179.3324 +                                        }
179.3325 +                                        else
179.3326 +                                        {*/
179.3327 +                                                AH=tempw2&0xFF;
179.3328 +                                                tempws/=(int)((int8_t)temp);
179.3329 +                                                AL=tempws&0xFF;
179.3330 +//                                        }
179.3331 +                                }
179.3332 +                                else
179.3333 +                                {
179.3334 +                                        printf("IDIVb BY 0 %04X:%04X\n",cs>>4,pc);
179.3335 +                                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3336 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
179.3337 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
179.3338 +                                        SP-=6;
179.3339 +                                        flags&=~I_FLAG;
179.3340 +                                        flags&=~T_FLAG;
179.3341 +                                        pc=readmemw(0,0);
179.3342 +//                        printf("F6 38\n");
179.3343 +                                        loadcs(readmemw(0,2));
179.3344 +                                        FETCHCLEAR();
179.3345 +//                                                cs=loadcs(CS);
179.3346 +//                                                cs=CS<<4;
179.3347 +//                                        printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
179.3348 +                                }
179.3349 +                                cycles-=101;
179.3350 +                                break;
179.3351 +
179.3352 +//                                default:
179.3353 +//                                printf("Bad F6 opcode %02X\n",rmdat&0x38);
179.3354 +//                                dumpregs();
179.3355 +//                                exit(-1);
179.3356 +                        }
179.3357 +                        break;
179.3358 +
179.3359 +                        case 0xF7:
179.3360 +                        fetchea();
179.3361 +                        tempw=geteaw();
179.3362 +                        switch (rmdat&0x38)
179.3363 +                        {
179.3364 +                                case 0x00: /*TEST w*/
179.3365 +                                tempw2=getword();
179.3366 +                                setznp16(tempw&tempw2);
179.3367 +                                flags&=~(C_FLAG|V_FLAG|A_FLAG);
179.3368 +                                cycles-=((mod==3)?5:11);
179.3369 +                                break;
179.3370 +                                case 0x10: /*NOT w*/
179.3371 +                                seteaw(~tempw);
179.3372 +                                cycles-=((mod==3)?3:24);
179.3373 +                                break;
179.3374 +                                case 0x18: /*NEG w*/
179.3375 +                                setsub16(0,tempw);
179.3376 +                                tempw=0-tempw;
179.3377 +                                seteaw(tempw);
179.3378 +                                cycles-=((mod==3)?3:24);
179.3379 +                                break;
179.3380 +                                case 0x20: /*MUL AX,w*/
179.3381 +                                setznp16(AX);
179.3382 +                                templ=AX*tempw;
179.3383 +//                                if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ);
179.3384 +                                AX=templ&0xFFFF;
179.3385 +                                DX=templ>>16;
179.3386 +                                if (AX|DX) flags&=~Z_FLAG;
179.3387 +                                else       flags|=Z_FLAG;
179.3388 +                                if (DX)    flags|=(C_FLAG|V_FLAG);
179.3389 +                                else       flags&=~(C_FLAG|V_FLAG);
179.3390 +                                cycles-=118;
179.3391 +                                break;
179.3392 +                                case 0x28: /*IMUL AX,w*/
179.3393 +                                setznp16(AX);
179.3394 +//                                printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
179.3395 +                                tempws=(int)((int16_t)AX)*(int)((int16_t)tempw);
179.3396 +                                if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG);
179.3397 +                                else                                    flags&=~(C_FLAG|V_FLAG);
179.3398 +//                                printf("%i ",tempws);
179.3399 +                                AX=tempws&0xFFFF;
179.3400 +                                tempws=(uint16_t)(tempws>>16);
179.3401 +                                DX=tempws&0xFFFF;
179.3402 +//                                printf("%04X %04X\n",AX,DX);
179.3403 +//                                dumpregs();
179.3404 +//                                exit(-1);
179.3405 +                                if (AX|DX) flags&=~Z_FLAG;
179.3406 +                                else       flags|=Z_FLAG;
179.3407 +                                cycles-=128;
179.3408 +                                break;
179.3409 +                                case 0x30: /*DIV AX,w*/
179.3410 +                                templ=(DX<<16)|AX;
179.3411 +//                                printf("DIV %08X/%04X\n",templ,tempw);
179.3412 +                                if (tempw)
179.3413 +                                {
179.3414 +                                        tempw2=templ%tempw;
179.3415 +                                        DX=tempw2;
179.3416 +                                        templ/=tempw;
179.3417 +                                        AX=templ&0xFFFF;
179.3418 +                                }
179.3419 +                                else
179.3420 +                                {
179.3421 +                                        printf("DIVw BY 0 %04X:%04X\n",cs>>4,pc);
179.3422 +                                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3423 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
179.3424 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
179.3425 +                                        SP-=6;
179.3426 +                                        flags&=~I_FLAG;
179.3427 +                                        flags&=~T_FLAG;
179.3428 +                                        pc=readmemw(0,0);
179.3429 +//                        printf("F7 30\n");
179.3430 +                                        loadcs(readmemw(0,2));
179.3431 +                                        FETCHCLEAR();
179.3432 +                                }
179.3433 +                                cycles-=144;
179.3434 +                                break;
179.3435 +                                case 0x38: /*IDIV AX,w*/
179.3436 +                                tempws=(int)((DX<<16)|AX);
179.3437 +//                                printf("IDIV %i %i ",tempws,tempw);
179.3438 +                                if (tempw)
179.3439 +                                {
179.3440 +                                        tempw2=tempws%(int)((int16_t)tempw);
179.3441 +//                                        printf("%04X ",tempw2);
179.3442 +                                                DX=tempw2;
179.3443 +                                                tempws/=(int)((int16_t)tempw);
179.3444 +                                                AX=tempws&0xFFFF;
179.3445 +                                }
179.3446 +                                else
179.3447 +                                {
179.3448 +                                        printf("IDIVw BY 0 %04X:%04X\n",cs>>4,pc);
179.3449 +                                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3450 +                                        writememw(ss,(SP-4)&0xFFFF,CS);
179.3451 +                                        writememw(ss,(SP-6)&0xFFFF,pc);
179.3452 +                                        SP-=6;
179.3453 +                                        flags&=~I_FLAG;
179.3454 +                                        flags&=~T_FLAG;
179.3455 +                                        pc=readmemw(0,0);
179.3456 +//                        printf("F7 38\n");
179.3457 +                                        loadcs(readmemw(0,2));
179.3458 +                                        FETCHCLEAR();
179.3459 +                                }
179.3460 +                                cycles-=165;
179.3461 +                                break;
179.3462 +
179.3463 +//                                default:
179.3464 +//                                printf("Bad F7 opcode %02X\n",rmdat&0x38);
179.3465 +//                                dumpregs();
179.3466 +//                                exit(-1);
179.3467 +                        }
179.3468 +                        break;
179.3469 +
179.3470 +                        case 0xF8: /*CLC*/
179.3471 +                        flags&=~C_FLAG;
179.3472 +                        cycles-=2;
179.3473 +                        break;
179.3474 +                        case 0xF9: /*STC*/
179.3475 +//                        printf("STC %04X\n",pc);
179.3476 +                        flags|=C_FLAG;
179.3477 +                        cycles-=2;
179.3478 +                        break;
179.3479 +                        case 0xFA: /*CLI*/
179.3480 +                        flags&=~I_FLAG;
179.3481 +//                        printf("CLI at %04X:%04X\n",cs>>4,pc);
179.3482 +                        cycles-=3;
179.3483 +                        break;
179.3484 +                        case 0xFB: /*STI*/
179.3485 +                        flags|=I_FLAG;
179.3486 +//                        printf("STI at %04X:%04X\n",cs>>4,pc);
179.3487 +                        cycles-=2;
179.3488 +                        break;
179.3489 +                        case 0xFC: /*CLD*/
179.3490 +                        flags&=~D_FLAG;
179.3491 +                        cycles-=2;
179.3492 +                        break;
179.3493 +                        case 0xFD: /*STD*/
179.3494 +                        flags|=D_FLAG;
179.3495 +                        cycles-=2;
179.3496 +                        break;
179.3497 +
179.3498 +                        case 0xFE: /*INC/DEC b*/
179.3499 +                        fetchea();
179.3500 +                        temp=geteab();
179.3501 +                        flags&=~V_FLAG;
179.3502 +                        if (rmdat&0x38)
179.3503 +                        {
179.3504 +                                setsub8nc(temp,1);
179.3505 +                                temp2=temp-1;
179.3506 +                                if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
179.3507 +                        }
179.3508 +                        else
179.3509 +                        {
179.3510 +                                setadd8nc(temp,1);
179.3511 +                                temp2=temp+1;
179.3512 +                                if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
179.3513 +                        }
179.3514 +//                        setznp8(temp2);
179.3515 +                        seteab(temp2);
179.3516 +                        cycles-=((mod==3)?3:23);
179.3517 +                        break;
179.3518 +
179.3519 +                        case 0xFF:
179.3520 +                        fetchea();
179.3521 +                        switch (rmdat&0x38)
179.3522 +                        {
179.3523 +                                case 0x00: /*INC w*/
179.3524 +                                tempw=geteaw();
179.3525 +                                setadd16nc(tempw,1);
179.3526 +//                                setznp16(tempw+1);
179.3527 +                                seteaw(tempw+1);
179.3528 +                                cycles-=((mod==3)?3:23);
179.3529 +                                break;
179.3530 +                                case 0x08: /*DEC w*/
179.3531 +                                tempw=geteaw();
179.3532 +//                                setsub16(tempw,1);
179.3533 +                                setsub16nc(tempw,1);
179.3534 +//                                setznp16(tempw-1);
179.3535 +                                seteaw(tempw-1);
179.3536 +//                                if (output) printf("DEC - %04X\n",tempw);
179.3537 +                                cycles-=((mod==3)?3:23);
179.3538 +                                break;
179.3539 +                                case 0x10: /*CALL*/
179.3540 +                                tempw=geteaw();
179.3541 +                                if (ssegs) ss=oldss;
179.3542 +                                writememw(ss,(SP-2)&0xFFFF,pc);
179.3543 +                                SP-=2;
179.3544 +                                pc=tempw;
179.3545 +//                        printf("FF 10\n");
179.3546 +                                cycles-=((mod==3)?20:29);
179.3547 +                                FETCHCLEAR();
179.3548 +                                break;
179.3549 +                                case 0x18: /*CALL far*/
179.3550 +                                tempw=readmemw(easeg,eaaddr);
179.3551 +                                tempw2=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
179.3552 +                                tempw3=CS;
179.3553 +                                tempw4=pc;
179.3554 +                                if (ssegs) ss=oldss;
179.3555 +                                pc=tempw;
179.3556 +//                        printf("FF 18\n");
179.3557 +                                loadcs(tempw2);
179.3558 +                                writememw(ss,(SP-2)&0xFFFF,tempw3);
179.3559 +                                writememw(ss,((SP-4)&0xFFFF),tempw4);
179.3560 +                                SP-=4;
179.3561 +                                cycles-=53;
179.3562 +                                FETCHCLEAR();
179.3563 +                                break;
179.3564 +                                case 0x20: /*JMP*/
179.3565 +                                pc=geteaw();
179.3566 +//                        printf("FF 20\n");
179.3567 +                                cycles-=((mod==3)?11:18);
179.3568 +                                FETCHCLEAR();
179.3569 +                                break;
179.3570 +                                case 0x28: /*JMP far*/
179.3571 +                                pc=readmemw(easeg,eaaddr); //geteaw();
179.3572 +//                        printf("FF 28\n");
179.3573 +                                loadcs(readmemw(easeg,(eaaddr+2)&0xFFFF)); //geteaw2();
179.3574 +//                                cs=loadcs(CS);
179.3575 +//                                cs=CS<<4;
179.3576 +                                cycles-=24;
179.3577 +                                FETCHCLEAR();
179.3578 +                                break;
179.3579 +                                case 0x30: /*PUSH w*/
179.3580 +                                tempw=geteaw();
179.3581 +//                                if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]);
179.3582 +                                if (ssegs) ss=oldss;
179.3583 +                                writememw(ss,((SP-2)&0xFFFF),tempw);
179.3584 +                                SP-=2;
179.3585 +                                cycles-=((mod==3)?15:24);
179.3586 +                                break;
179.3587 +
179.3588 +//                                default:
179.3589 +//                                printf("Bad FF opcode %02X\n",rmdat&0x38);
179.3590 +//                                dumpregs();
179.3591 +//                                exit(-1);
179.3592 +                        }
179.3593 +                        break;
179.3594 +
179.3595 +                        default:
179.3596 +                        FETCH();
179.3597 +                        cycles-=8;
179.3598 +                        break;
179.3599 +
179.3600 +/*                        printf("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
179.3601 +                        dumpregs();
179.3602 +                        exit(-1);*/
179.3603 +                }
179.3604 +                pc&=0xFFFF;
179.3605 +
179.3606 +/*                if ((CS & 0xf000) == 0xa000)
179.3607 +                {
179.3608 +                        dumpregs();
179.3609 +                        exit(-1);
179.3610 +                }*/
179.3611 +//                output = 3;
179.3612 +/*                if (CS == 0xf000)
179.3613 +                {
179.3614 +                        dumpregs();
179.3615 +                        exit(-1);
179.3616 +                }
179.3617 +                output = 3;*/
179.3618 +                if (ssegs)
179.3619 +                {
179.3620 +                        ds=oldds;
179.3621 +                        ss=oldss;
179.3622 +                        ssegs=0;
179.3623 +                }
179.3624 +                
179.3625 +//                output = 3;
179.3626 +               // if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
179.3627 +                FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
179.3628 +                if ((cycdiff-cycles)<memcycs) cycles-=(memcycs-(cycdiff-cycles));
179.3629 +                if (romset==ROM_IBMPC)
179.3630 +                {
179.3631 +                        if ((cs+pc)==0xFE4A7) /*You didn't seriously think I was going to emulate the cassette, did you?*/
179.3632 +                        {
179.3633 +                                CX=1;
179.3634 +                                BX=0x500;
179.3635 +                        }
179.3636 +                }
179.3637 +                memcycs=0;
179.3638 +
179.3639 +                insc++;
179.3640 +//                output=(CS==0xEB9);
179.3641 +                clockhardware();
179.3642 +
179.3643 +
179.3644 +                if (trap && (flags&T_FLAG) && !noint)
179.3645 +                {
179.3646 +//                        printf("TRAP!!! %04X:%04X\n",CS,pc);
179.3647 +                        writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3648 +                        writememw(ss,(SP-4)&0xFFFF,CS);
179.3649 +                        writememw(ss,(SP-6)&0xFFFF,pc);
179.3650 +                        SP-=6;
179.3651 +                        addr=1<<2;
179.3652 +                        flags&=~I_FLAG;
179.3653 +                        flags&=~T_FLAG;
179.3654 +                        pc=readmemw(0,addr);
179.3655 +                        loadcs(readmemw(0,addr+2));
179.3656 +                        FETCHCLEAR();
179.3657 +                }
179.3658 +                else if ((flags&I_FLAG) && (pic.pend&~pic.mask) && !ssegs && !noint)
179.3659 +                {
179.3660 +                        temp=picinterrupt();
179.3661 +                        if (temp!=0xFF)
179.3662 +                        {
179.3663 +                                if (inhlt) pc++;
179.3664 +                                writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
179.3665 +                                writememw(ss,(SP-4)&0xFFFF,CS);
179.3666 +                                writememw(ss,(SP-6)&0xFFFF,pc);
179.3667 +                                SP-=6;
179.3668 +                                addr=temp<<2;
179.3669 +                                flags&=~I_FLAG;
179.3670 +                                flags&=~T_FLAG;
179.3671 +                                pc=readmemw(0,addr);
179.3672 +//                        printf("INT INT INT\n");
179.3673 +                                loadcs(readmemw(0,addr+2));
179.3674 +                                FETCHCLEAR();
179.3675 +                                inint=1;
179.3676 +//                                printf("INTERRUPT\n");
179.3677 +                        }
179.3678 +                }
179.3679 +
179.3680 +                if (noint) noint=0;
179.3681 +                ins++;
179.3682 +/*                if (timetolive)
179.3683 +                {
179.3684 +                        timetolive--;
179.3685 +                        if (!timetolive) exit(-1); //output=0;
179.3686 +                }*/
179.3687 +        }
179.3688 +}
179.3689 +
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/src/x86.h	Sun Apr 21 14:54:35 2013 +0100
   180.3 @@ -0,0 +1,98 @@
   180.4 +uint32_t old8,old82,old83;
   180.5 +uint16_t oldcs;
   180.6 +uint32_t oldpc;
   180.7 +extern uint32_t rmdat32;
   180.8 +int oldcpl;
   180.9 +
  180.10 +int tempc;
  180.11 +int cycles,output;
  180.12 +int ssegs;
  180.13 +int firstrepcycle;
  180.14 +
  180.15 +uint32_t easeg,eaaddr,ealimit,ealimitw;
  180.16 +int rm,reg,mod,rmdat;
  180.17 +
  180.18 +int skipnextprint;
  180.19 +int inhlt;
  180.20 +
  180.21 +uint8_t opcode;
  180.22 +int ins,noint,notpresent;
  180.23 +int inint;
  180.24 +
  180.25 +uint16_t lastcs,lastpc;
  180.26 +int lldt;
  180.27 +int timetolive,keyboardtimer;
  180.28 +
  180.29 +#define setznp168 setznp16
  180.30 +
  180.31 +#define getr8(r)   ((r&4)?regs[r&3].b.h:regs[r&3].b.l)
  180.32 +#define getr16(r)  regs[r].w
  180.33 +#define getr32(r)  regs[r].l
  180.34 +
  180.35 +#define setr8(r,v) if (r&4) regs[r&3].b.h=v; \
  180.36 +                   else     regs[r&3].b.l=v;
  180.37 +#define setr16(r,v) regs[r].w=v
  180.38 +#define setr32(r,v) regs[r].l=v
  180.39 +
  180.40 +uint8_t znptable8[256];
  180.41 +uint16_t znptable16[65536];
  180.42 +
  180.43 +int use32;
  180.44 +int stack32;
  180.45 +
  180.46 +#define fetchea()   { rmdat=readmemb(cs+pc); pc++;  \
  180.47 +                    reg=(rmdat>>3)&7;               \
  180.48 +                    mod=(rmdat>>6)&3;               \
  180.49 +                    rm=rmdat&7;                   \
  180.50 +                    if (mod!=3) fetcheal(); }
  180.51 +
  180.52 +
  180.53 +int optype;
  180.54 +#define JMP 1
  180.55 +#define CALL 2
  180.56 +#define IRET 3
  180.57 +#define INT 4
  180.58 +
  180.59 +uint32_t oxpc;
  180.60 +
  180.61 +extern uint16_t *mod1add[2][8];
  180.62 +extern uint32_t *mod1seg[8];
  180.63 +
  180.64 +
  180.65 +#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !ssegs && !noint)
  180.66 +
  180.67 +extern int cgate32;
  180.68 +
  180.69 +
  180.70 +extern uint32_t *eal_r, *eal_w;
  180.71 +
  180.72 +
  180.73 +extern uint32_t flags_zn;
  180.74 +extern uint8_t flags_p;
  180.75 +#define FLAG_N (flags_zn>>31)
  180.76 +#define FLAG_Z (flags_zn)
  180.77 +#define FLAG_P (znptable8[flags_p]&P_FLAG)
  180.78 +
  180.79 +extern int gpf;
  180.80 +
  180.81 +
  180.82 +enum
  180.83 +{
  180.84 +        ABRT_NONE = 0,
  180.85 +        ABRT_GEN,
  180.86 +        ABRT_TS  = 0xA,
  180.87 +        ABRT_NP  = 0xB,
  180.88 +        ABRT_SS  = 0xC,
  180.89 +        ABRT_GPF = 0xD,
  180.90 +        ABRT_PF  = 0xE
  180.91 +};
  180.92 +
  180.93 +extern int abrt;
  180.94 +extern uint32_t abrt_error;
  180.95 +
  180.96 +void x86_doabrt(int x86_abrt);
  180.97 +
  180.98 +extern uint8_t opcode2;
  180.99 +
 180.100 +extern uint16_t rds;
 180.101 +extern uint32_t rmdat32;
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/src/x86_flags.h	Sun Apr 21 14:54:35 2013 +0100
   181.3 @@ -0,0 +1,17 @@
   181.4 +static inline void setznp8(uint8_t val)
   181.5 +{
   181.6 +        flags&=~0x8d5;
   181.7 +        flags|=znptable8[val];
   181.8 +}
   181.9 +
  181.10 +static inline void setznp16(uint16_t val)
  181.11 +{
  181.12 +        flags&=~0x8d5;
  181.13 +        flags|=znptable16[val];
  181.14 +}
  181.15 +static inline void setznp32(uint32_t val)
  181.16 +{
  181.17 +        flags&=~0x8d5;
  181.18 +        flags|=((val&0x80000000)?N_FLAG:((!val)?Z_FLAG:0));
  181.19 +        flags|=znptable8[val&0xFF]&P_FLAG;
  181.20 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/src/x86seg.c	Sun Apr 21 14:54:35 2013 +0100
   182.3 @@ -0,0 +1,2543 @@
   182.4 +//#if 0
   182.5 +#include <stdio.h>
   182.6 +#include <stdarg.h>
   182.7 +#include "ibm.h"
   182.8 +#include "x86.h"
   182.9 +
  182.10 +/*Controls whether the accessed bit in a descriptor is set when CS is loaded. The
  182.11 +  386 PRM is ambiguous on this subject, but BOCHS doesn't set it and Windows 98
  182.12 +  setup crashes if it is.
  182.13 +  The accessed bit is always set for data and stack selectors though.*/
  182.14 +//#define CS_ACCESSED
  182.15 +
  182.16 +/*Controls whether the accessed bit in a descriptor is set when a data or stack
  182.17 +  selector is loaded. This SHOULD be set, however Windows 98 setup crashes if it
  182.18 +  is.*/
  182.19 +//#define SEL_ACCESSED
  182.20 +int stimes = 0;
  182.21 +int dtimes = 0;
  182.22 +int btimes = 0;
  182.23 +int is486=1;
  182.24 +
  182.25 +uint32_t abrt_error;
  182.26 +int cgate16,cgate32;
  182.27 +
  182.28 +#define breaknullsegs 0
  182.29 +
  182.30 +int intgatesize;
  182.31 +
  182.32 +void taskswitch286(uint16_t seg, uint16_t *segdat, int is32);
  182.33 +void taskswitch386(uint16_t seg, uint16_t *segdat);
  182.34 +
  182.35 +int notpresent=0;
  182.36 +int output;
  182.37 +void pmodeint(int num, int soft);
  182.38 +/*NOT PRESENT is INT 0B
  182.39 +  GPF is INT 0D*/
  182.40 +
  182.41 +FILE *pclogf;
  182.42 +void x86abort(const char *format, ...)
  182.43 +{
  182.44 +   char buf[256];
  182.45 +//   return;
  182.46 +   if (!pclogf)
  182.47 +      pclogf=fopen("pclog.txt","wt");
  182.48 +//return;
  182.49 +   va_list ap;
  182.50 +   va_start(ap, format);
  182.51 +   vsprintf(buf, format, ap);
  182.52 +   va_end(ap);
  182.53 +   fputs(buf,pclogf);
  182.54 +   fflush(pclogf);
  182.55 +   dumpregs();
  182.56 +   exit(-1);
  182.57 +}
  182.58 +
  182.59 +uint8_t opcode2;
  182.60 +
  182.61 +void x86_doabrt(int x86_abrt)
  182.62 +{
  182.63 +//        ingpf = 1;
  182.64 +        CS = oldcs;
  182.65 +        pc = oldpc;
  182.66 +        _cs.access = oldcpl << 5;
  182.67 +//        pclog("x86_doabrt - %02X %08X  %04X:%08X  %i\n", x86_abrt, abrt_error, CS, pc, ins);
  182.68 +        
  182.69 +/*        if (CS == 0x3433 && pc == 0x000006B0)
  182.70 +        {
  182.71 +                pclog("Quit it\n");
  182.72 +                dumpregs();
  182.73 +                exit(-1);
  182.74 +        }*/
  182.75 +//        pclog("GPF! - error %04X  %04X(%08X):%08X %02X %02X  %i  %04X %i %i\n",error,CS,cs,pc,opcode,opcode2,ins,flags&I_FLAG,IOPL, dtimes);
  182.76 +
  182.77 +        pmodeint(x86_abrt, 0);
  182.78 +        
  182.79 +        if (abrt) return;
  182.80 +        
  182.81 +        if (intgatesize == 16)
  182.82 +        {
  182.83 +                if (stack32)
  182.84 +                {
  182.85 +                        writememw(ss, ESP-2, abrt_error);
  182.86 +                        ESP-=2;
  182.87 +                }
  182.88 +                else
  182.89 +                {
  182.90 +                        writememw(ss, ((SP-2)&0xFFFF), abrt_error);
  182.91 +                        SP-=2;
  182.92 +                }
  182.93 +        }
  182.94 +        else
  182.95 +        {
  182.96 +                if (stack32)
  182.97 +                {
  182.98 +                        writememl(ss, ESP-4, abrt_error);
  182.99 +                        ESP-=4;
 182.100 +                }
 182.101 +                else
 182.102 +                {
 182.103 +                        writememl(ss, ((SP-4)&0xFFFF), abrt_error);
 182.104 +                        SP-=4;
 182.105 +                }
 182.106 +        }
 182.107 +//        ingpf = 0;
 182.108 +//        abrt = gpf = 1;
 182.109 +}
 182.110 +void x86gpf(char *s, uint16_t error)
 182.111 +{
 182.112 +//        pclog("GPF %04X\n", error);
 182.113 +        abrt = ABRT_GPF;
 182.114 +        abrt_error = error;
 182.115 +}
 182.116 +void x86ss(char *s, uint16_t error)
 182.117 +{
 182.118 +//        pclog("SS %04X\n", error);
 182.119 +        abrt = ABRT_SS;
 182.120 +        abrt_error = error;
 182.121 +}
 182.122 +void x86ts(char *s, uint16_t error)
 182.123 +{
 182.124 +//        pclog("TS %04X\n", error);
 182.125 +        abrt = ABRT_TS;
 182.126 +        abrt_error = error;
 182.127 +}
 182.128 +void x86np(char *s, uint16_t error)
 182.129 +{
 182.130 +//        pclog("NP %04X : %s\n", error, s);
 182.131 +//        dumpregs();
 182.132 +//        exit(-1);
 182.133 +        abrt = ABRT_NP;
 182.134 +        abrt_error = error;
 182.135 +}
 182.136 +
 182.137 +
 182.138 +void loadseg(uint16_t seg, x86seg *s)
 182.139 +{
 182.140 +        uint16_t segdat[4];
 182.141 +        uint32_t addr;
 182.142 +        int dpl;
 182.143 +        if (output) pclog("Load seg %04X\n",seg);
 182.144 +        if (msw&1 && !(eflags&VM_FLAG))
 182.145 +        {
 182.146 +//                intcount++;
 182.147 +                if (!(seg&~3))
 182.148 +                {
 182.149 +                        if (s==&_ss)
 182.150 +                        {
 182.151 +                                pclog("SS selector = NULL!\n");
 182.152 +                                x86ss(NULL,0);
 182.153 +                                return;
 182.154 +//                                dumpregs();
 182.155 +//                                exit(-1);
 182.156 +                        }
 182.157 +//                        if (s->base!=-1) pclog("NEW! ");
 182.158 +                        s->seg=0;
 182.159 +                        s->base=-1;
 182.160 +//                        pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc);
 182.161 +                        return;
 182.162 +                }
 182.163 +//                if (s==&_ss) pclog("Load SS %04X\n",seg);
 182.164 +//                pclog("Protected mode seg load!\n");
 182.165 +                addr=seg&~7;
 182.166 +                if (seg&4)
 182.167 +                {
 182.168 +                        if (addr>=ldt.limit)
 182.169 +                        {
 182.170 +                                pclog("Bigger than LDT limit %04X %04X %02X %02X %02X\n",seg,ldt.limit, opcode, opcode2, rmdat);
 182.171 +//                                dumppic();
 182.172 +//                                dumpregs();
 182.173 +//                                exit(-1);
 182.174 +                                x86gpf(NULL,seg&~3);
 182.175 +                                return;
 182.176 +                        }
 182.177 +                        addr+=ldt.base;
 182.178 +                }
 182.179 +                else
 182.180 +                {
 182.181 +                        if (addr>=gdt.limit)
 182.182 +                        {
 182.183 +                                pclog("Bigger than GDT limit %04X %04X 1\n",seg,gdt.limit);
 182.184 +//                                dumpregs();
 182.185 +//                                exit(-1);
 182.186 +                                x86gpf(NULL,seg&~3);
 182.187 +                                return;
 182.188 +                        }
 182.189 +                        addr+=gdt.base;
 182.190 +                }
 182.191 +                cpl_override=1;
 182.192 +                segdat[0]=readmemw(0,addr);
 182.193 +                segdat[1]=readmemw(0,addr+2);
 182.194 +                segdat[2]=readmemw(0,addr+4);
 182.195 +                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.196 +                dpl=(segdat[2]>>13)&3;
 182.197 +                if (s==&_ss)
 182.198 +                {
 182.199 +                        if (!(seg&~3))
 182.200 +                        {
 182.201 +                                pclog("Load SS null selector\n");
 182.202 +                                x86gpf(NULL,seg&~3);
 182.203 +                                return;
 182.204 +                        }
 182.205 +                        if ((seg&3)!=CPL || dpl!=CPL)
 182.206 +                        {
 182.207 +                                pclog("Invalid SS permiss\n");
 182.208 +                                x86gpf(NULL,seg&~3);
 182.209 +//                                x86abort("Invalid SS permiss for %04X!\n",seg&0xFFFC);
 182.210 +                                return;
 182.211 +                        }
 182.212 +                        switch ((segdat[2]>>8)&0x1F)
 182.213 +                        {
 182.214 +                                case 0x12: case 0x13: case 0x16: case 0x17: /*r/w*/
 182.215 +                                break;
 182.216 +                                default:
 182.217 +                                pclog("Invalid SS type\n");
 182.218 +                                x86gpf(NULL,seg&~3);
 182.219 +//                                x86abort("Invalid SS segment type for %04X!\n",seg&0xFFFC);
 182.220 +                                return;
 182.221 +                        }
 182.222 +                        if (!(segdat[2]&0x8000))
 182.223 +                        {
 182.224 +                                pclog("Load SS not present!\n");
 182.225 +                                x86ss(NULL,seg&~3);
 182.226 +                                return;
 182.227 +                        }
 182.228 +                        if (segdat[3]&0x40) stack32=1;
 182.229 +                        else                stack32=0;
 182.230 +//                        pclog("Load SS\n");
 182.231 +                }
 182.232 +                else if (s!=&_cs)
 182.233 +                {
 182.234 +                        if (output) pclog("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]);
 182.235 +                        if (output) pclog("Seg type %03X\n",segdat[2]&0x1F00);
 182.236 +                        switch ((segdat[2]>>8)&0x1F)
 182.237 +                        {
 182.238 +                                case 0x10: case 0x11: case 0x12: case 0x13: /*Data segments*/
 182.239 +                                case 0x14: case 0x15: case 0x16: case 0x17:
 182.240 +                                case 0x1A: case 0x1B: /*Readable non-conforming code*/
 182.241 +//                                pclog("Load seg %04X %i %i %04X:%08X\n",seg,dpl,CS&3,CS,pc);
 182.242 +                                if ((seg&3)>dpl || (CPL)>dpl)
 182.243 +                                {
 182.244 +                                        pclog("Data seg fail - %04X:%08X %04X %i %04X\n",CS,pc,seg,dpl,segdat[2]);
 182.245 +                                        x86gpf(NULL,seg&~3);
 182.246 +//                                        x86abort("Data segment load - level too low!\n",seg&0xFFFC);
 182.247 +                                        return;
 182.248 +                                }
 182.249 +                                break;
 182.250 +                                case 0x1E: case 0x1F: /*Readable conforming code*/
 182.251 +                                break;
 182.252 +                                default:
 182.253 +                                pclog("Invalid segment type for %04X! %04X\n",seg&0xFFFC,segdat[2]);
 182.254 +//                                if ((seg & ~3) == 0x1508) btimes++;
 182.255 +//                                if (btimes == 2) output = 3;
 182.256 +//                                dumpregs();
 182.257 +//                                exit(-1);
 182.258 +                                x86gpf(NULL,seg&~3);
 182.259 +//                                x86abort("Invalid segment type for %04X!\n",seg&0xFFFC);
 182.260 +                                return;
 182.261 +                        }
 182.262 +                }
 182.263 +//                #endif
 182.264 +//                }
 182.265 +//                if (!(segdat[2]&0x8000)) x86abort("Data segment not present!\n");
 182.266 +//                if (!(segdat[2]&0x800) || !(segdat[2]&0x400))
 182.267 +//                {
 182.268 +                        if (!(segdat[2]&0x8000))
 182.269 +                        {
 182.270 +                                x86np("Load data seg not present", seg & 0xfffc);
 182.271 +                                return;
 182.272 +                        }
 182.273 +                        s->seg=seg;
 182.274 +                        s->limit=segdat[0]|((segdat[3]&0xF)<<16);
 182.275 +                        if (segdat[3]&0x80) s->limit=(s->limit<<12)|0xFFF;
 182.276 +                        s->limitw=(segdat[2]&0x200)?1:0;
 182.277 +                        s->base=segdat[1];
 182.278 +                        s->base|=((segdat[2]&0xFF)<<16);
 182.279 +                        if (is386) s->base|=((segdat[3]>>8)<<24);
 182.280 +                        s->access=segdat[2]>>8;
 182.281 +                        
 182.282 +                        if ((segdat[2]>>8) & 4)
 182.283 +                           s->limit = 0xffffffff;
 182.284 +                           
 182.285 +//                        if (output) pclog("SS limit %08X\n", s->limit);
 182.286 +                        
 182.287 +//                        pclog("Seg Write %04X to %08X\n",segdat[2]|0x100,addr+4);
 182.288 +#ifndef CS_ACCESSED
 182.289 +                        if (s != &_cs)
 182.290 +                        {
 182.291 +#endif                   
 182.292 +#ifdef SEL_ACCESSED         
 182.293 +                                cpl_override = 1;
 182.294 +                                writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
 182.295 +                                cpl_override = 0;
 182.296 +#endif
 182.297 +#ifndef CS_ACCESSED
 182.298 +                        }
 182.299 +#endif
 182.300 +//                        pclog("Access=%02X Limit=%04X Limitw=%04X   %08X  %i %04X:%04X\n",s->access,s->limit,s->limitw, _ss.limit, ins, CS, pc);
 182.301 +//                        if (s==&_es && s->base>0x180000) s->base=0x180000;
 182.302 +//                }
 182.303 +//                pclog("base=%06X limit=%04X access=%02X  %06X  %04X %04X %04X  %04X\n",s->base,s->limit,s->access,addr,segdat[0],segdat[1],segdat[2],seg);
 182.304 +//                dumpregs();
 182.305 +//                exit(-1);
 182.306 +        }
 182.307 +        else
 182.308 +        {
 182.309 +                s->base=seg<<4;
 182.310 +                s->limit=0xFFFF;
 182.311 +                s->seg=seg;
 182.312 +                if (eflags&VM_FLAG) s->access=3<<5;
 182.313 +                else                s->access=0<<5;
 182.314 +                use32=0;
 182.315 +                if (s==&_ss) stack32=0;
 182.316 +/*                if (s==&_ds)
 182.317 +                {
 182.318 +                        pclog("DS! %04X %06X %04X:%04X\n",DS,ds,CS,pc);
 182.319 +                }*/
 182.320 +        }
 182.321 +}
 182.322 +
 182.323 +#define DPL ((segdat[2]>>13)&3)
 182.324 +#define DPL2 ((segdat2[2]>>13)&3)
 182.325 +#define DPL3 ((segdat3[2]>>13)&3)
 182.326 +
 182.327 +void loadcs(uint16_t seg)
 182.328 +{
 182.329 +        uint16_t segdat[4];
 182.330 +        uint32_t addr;
 182.331 +        int count;
 182.332 +        uint16_t oldss,oldsp;
 182.333 +        if (output) pclog("Load CS %04X\n",seg);
 182.334 +        if (msw&1 && !(eflags&VM_FLAG))
 182.335 +        {
 182.336 +//                intcount++;
 182.337 +//                flushmmucache();
 182.338 +//                pclog("Load CS %04X\n",seg);
 182.339 +                if (!(seg&~3))
 182.340 +                {
 182.341 +                        pclog("Trying to load CS with NULL selector! lcs\n");
 182.342 +//                        dumpregs();
 182.343 +//                        exit(-1);
 182.344 +                        x86gpf(NULL,0);
 182.345 +                        return;
 182.346 +                }
 182.347 +//                pclog("Protected mode CS load! %04X\n",seg);
 182.348 +                addr=seg&~7;
 182.349 +                if (seg&4)
 182.350 +                {
 182.351 +                        if (addr>=ldt.limit)
 182.352 +                        {
 182.353 +                                pclog("Bigger than LDT limit %04X %04X CS\n",seg,ldt.limit);
 182.354 +                                x86gpf(NULL,seg&~3);
 182.355 +                                return;
 182.356 +                        }
 182.357 +                        addr+=ldt.base;
 182.358 +                }
 182.359 +                else
 182.360 +                {
 182.361 +                        if (addr>=gdt.limit)
 182.362 +                        {
 182.363 +                                pclog("Bigger than GDT limit %04X %04X CS\n",seg,gdt.limit);
 182.364 +                                x86gpf(NULL,seg&~3);
 182.365 +                                return;
 182.366 +                        }
 182.367 +                        addr+=gdt.base;
 182.368 +                }
 182.369 +                cpl_override=1;
 182.370 +                segdat[0]=readmemw(0,addr);
 182.371 +                segdat[1]=readmemw(0,addr+2);
 182.372 +                segdat[2]=readmemw(0,addr+4);
 182.373 +                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.374 +                if (optype==JMP) pclog("Code seg - %04X - %04X %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2],segdat[3]);
 182.375 +//                if (!(segdat[2]&0x8000)) x86abort("Code segment not present!\n");
 182.376 +//                if (output) pclog("Segdat2 %04X\n",segdat[2]);
 182.377 +                if (segdat[2]&0x1000) /*Normal code segment*/
 182.378 +                {
 182.379 +                        if (!(segdat[2]&0x400)) /*Not conforming*/
 182.380 +                        {
 182.381 +                                if ((seg&3)>CPL)
 182.382 +                                {
 182.383 +                                        x86gpf(NULL,seg&~3);
 182.384 +                                        pclog("loadcs RPL > CPL %04X %04X %i %02X\n",segdat[2],seg,CPL,opcode);
 182.385 +                                        return;
 182.386 +                                }
 182.387 +                                if (CPL != DPL)
 182.388 +                                {
 182.389 +                                        x86gpf(NULL,seg&~3);
 182.390 +                                        return;
 182.391 +                                }
 182.392 +                        }
 182.393 +                        if (CPL < DPL)
 182.394 +                        {
 182.395 +                                x86gpf(NULL,seg&~3);
 182.396 +                                return;
 182.397 +                        }
 182.398 +                        if (!(segdat[2]&0x8000))
 182.399 +                        {
 182.400 +                                x86np("Load CS not present", seg & 0xfffc);
 182.401 +                                return;
 182.402 +                        }
 182.403 +                        if (segdat[3]&0x40) use32=0x300;
 182.404 +                        else                use32=0;
 182.405 +                        CS=(seg&~3)|CPL;
 182.406 +                        _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
 182.407 +                        if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
 182.408 +                        _cs.base=segdat[1];
 182.409 +                        _cs.base|=((segdat[2]&0xFF)<<16);
 182.410 +                        if (is386) _cs.base|=((segdat[3]>>8)<<24);
 182.411 +                        _cs.access=segdat[2]>>8;
 182.412 +                        use32=(segdat[3]&0x40)?0x300:0;
 182.413 +                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.414 +
 182.415 +#ifdef CS_ACCESSED                        
 182.416 +                        cpl_override = 1;
 182.417 +                        writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
 182.418 +                        cpl_override = 0;
 182.419 +#endif
 182.420 +//                        if (output) pclog("Load CS %08X\n",_cs.base);
 182.421 +//                        CS=(CS&0xFFFC)|((_cs.access>>5)&3);
 182.422 +                }
 182.423 +                else /*System segment*/
 182.424 +                {
 182.425 +                        if (!(segdat[2]&0x8000))
 182.426 +                        {
 182.427 +                                x86np("Load CS system seg not present\n", seg & 0xfffc);
 182.428 +                                return;
 182.429 +                        }
 182.430 +                        switch (segdat[2]&0xF00)
 182.431 +                        {
 182.432 +                                default:
 182.433 +                                pclog("Bad CS %02X %02X %i special descriptor %03X %04X\n",opcode,rmdat,optype,segdat[2]&0xF00,seg);
 182.434 +                                x86gpf(NULL,seg&~3);
 182.435 +                                return;
 182.436 +                        }
 182.437 +                }
 182.438 +//                pclog("CS = %04X base=%06X limit=%04X access=%02X  %04X\n",CS,cs,_cs.limit,_cs.access,addr);
 182.439 +//                dumpregs();
 182.440 +//                exit(-1);
 182.441 +        }
 182.442 +        else
 182.443 +        {
 182.444 +                _cs.base=seg<<4;
 182.445 +                _cs.limit=0xFFFF;
 182.446 +                CS=seg;
 182.447 +                if (eflags&VM_FLAG) _cs.access=3<<5;
 182.448 +                else                _cs.access=0<<5;
 182.449 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.450 +        }
 182.451 +}
 182.452 +
 182.453 +void loadcsjmp(uint16_t seg, uint32_t oxpc)
 182.454 +{
 182.455 +        uint16_t segdat[4];
 182.456 +        uint32_t addr;
 182.457 +        int count;
 182.458 +        uint16_t oldss,oldsp;
 182.459 +        uint16_t type,seg2;
 182.460 +        uint32_t newpc;
 182.461 +        if (output) pclog("Load CS JMP %04X\n",seg);
 182.462 +        if (msw&1 && !(eflags&VM_FLAG))
 182.463 +        {
 182.464 +                if (!(seg&~3))
 182.465 +                {
 182.466 +                        pclog("Trying to load CS with NULL selector! lcsjmp\n");
 182.467 +                        x86gpf(NULL,0);
 182.468 +                        return;
 182.469 +//                        dumpregs();
 182.470 +//                        exit(-1);
 182.471 +                }
 182.472 +                addr=seg&~7;
 182.473 +                if (seg&4)
 182.474 +                {
 182.475 +                        if (addr>=ldt.limit)
 182.476 +                        {
 182.477 +                                pclog("Bigger than LDT limit %04X %04X CS\n",seg,ldt.limit);
 182.478 +                                x86gpf(NULL,seg&~3);
 182.479 +                                return;
 182.480 +                        }
 182.481 +                        addr+=ldt.base;
 182.482 +                }
 182.483 +                else
 182.484 +                {
 182.485 +                        if (addr>=gdt.limit)
 182.486 +                        {
 182.487 +                                pclog("Bigger than GDT limit %04X %04X CS\n",seg,gdt.limit);
 182.488 +                                x86gpf(NULL,seg&~3);
 182.489 +                                return;
 182.490 +                        }
 182.491 +                        addr+=gdt.base;
 182.492 +                }
 182.493 +                cpl_override=1;
 182.494 +                segdat[0]=readmemw(0,addr);
 182.495 +                segdat[1]=readmemw(0,addr+2);
 182.496 +                segdat[2]=readmemw(0,addr+4);
 182.497 +                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.498 +                if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]);
 182.499 +                if (segdat[2]&0x1000) /*Normal code segment*/
 182.500 +                {
 182.501 +                        if (!(segdat[2]&0x400)) /*Not conforming*/
 182.502 +                        {
 182.503 +                                if ((seg&3)>CPL)
 182.504 +                                {
 182.505 +                                        x86gpf(NULL,seg&~3);
 182.506 +                                        return;
 182.507 +                                }
 182.508 +                                if (CPL != DPL)
 182.509 +                                {
 182.510 +                                        x86gpf(NULL,seg&~3);
 182.511 +                                        return;
 182.512 +                                }
 182.513 +                        }
 182.514 +                        if (CPL < DPL)
 182.515 +                        {
 182.516 +                                x86gpf(NULL,seg&~3);
 182.517 +                                return;
 182.518 +                        }
 182.519 +                        if (!(segdat[2]&0x8000))
 182.520 +                        {
 182.521 +                                x86np("Load CS JMP not present\n", seg & 0xfffc);
 182.522 +                                return;
 182.523 +                        }
 182.524 +                        if (segdat[3]&0x40) use32=0x300;
 182.525 +                        else                use32=0;
 182.526 +
 182.527 +#ifdef CS_ACCESSED                        
 182.528 +                        cpl_override = 1;
 182.529 +                        writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
 182.530 +                        cpl_override = 0;
 182.531 +#endif
 182.532 +                        
 182.533 +                        CS = (seg & ~3) | CPL;
 182.534 +                        segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8);
 182.535 +                        
 182.536 +                        _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
 182.537 +                        if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
 182.538 +                        _cs.base=segdat[1];
 182.539 +                        _cs.base|=((segdat[2]&0xFF)<<16);
 182.540 +                        if (is386) _cs.base|=((segdat[3]>>8)<<24);
 182.541 +                        _cs.access=segdat[2]>>8;
 182.542 +                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.543 +                        use32=(segdat[3]&0x40)?0x300:0;
 182.544 +                }
 182.545 +                else /*System segment*/
 182.546 +                {
 182.547 +                        if (!(segdat[2]&0x8000))
 182.548 +                        {
 182.549 +                                x86np("Load CS JMP system selector not present\n", seg & 0xfffc);
 182.550 +                                return;
 182.551 +                        }
 182.552 +                        type=segdat[2]&0xF00;
 182.553 +                        if (type==0x400) newpc=segdat[0];
 182.554 +                        else             newpc=segdat[0]|(segdat[3]<<16);
 182.555 +                        switch (type)
 182.556 +                        {
 182.557 +                                case 0x400: /*Call gate*/
 182.558 +                                case 0xC00:
 182.559 +                                cgate32=(type&0x800);
 182.560 +                                cgate16=!cgate32;
 182.561 +                                oldcs=CS;
 182.562 +                                oldpc=pc;
 182.563 +                                count=segdat[2]&31;
 182.564 +                                if ((DPL < CPL) || (DPL < (seg&3)))
 182.565 +                                {
 182.566 +                                        x86gpf(NULL,seg&~3);
 182.567 +                                        return;
 182.568 +                                }
 182.569 +                                if (!(segdat[2]&0x8000))
 182.570 +                                {
 182.571 +                                        x86np("Load CS JMP call gate not present\n", seg & 0xfffc);
 182.572 +                                        return;
 182.573 +                                }
 182.574 +                                seg2=segdat[1];
 182.575 +
 182.576 +                                if (!(seg2&~3))
 182.577 +                                {
 182.578 +                                        pclog("Trying to load CS with NULL selector! lcsjmpcg\n");
 182.579 +                                        x86gpf(NULL,0);
 182.580 +                                        return;
 182.581 +//                                        dumpregs();
 182.582 +//                                        exit(-1);
 182.583 +                                }
 182.584 +                                addr=seg2&~7;
 182.585 +                                if (seg2&4)
 182.586 +                                {
 182.587 +                                        if (addr>=ldt.limit)
 182.588 +                                        {
 182.589 +                                                pclog("Bigger than LDT limit %04X %04X CSJ\n",seg2,gdt.limit);
 182.590 +                                                x86gpf(NULL,seg2&~3);
 182.591 +                                                return;
 182.592 +                                        }
 182.593 +                                        addr+=ldt.base;
 182.594 +                                }
 182.595 +                                else
 182.596 +                                {
 182.597 +                                        if (addr>=gdt.limit)
 182.598 +                                        {
 182.599 +                                                pclog("Bigger than GDT limit %04X %04X CSJ\n",seg2,gdt.limit);
 182.600 +                                                x86gpf(NULL,seg2&~3);
 182.601 +                                                return;
 182.602 +                                        }
 182.603 +                                        addr+=gdt.base;
 182.604 +                                }
 182.605 +                                cpl_override=1;
 182.606 +                                segdat[0]=readmemw(0,addr);
 182.607 +                                segdat[1]=readmemw(0,addr+2);
 182.608 +                                segdat[2]=readmemw(0,addr+4);
 182.609 +                                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.610 +
 182.611 +                                if (DPL > CPL)
 182.612 +                                {
 182.613 +                                        x86gpf(NULL,seg2&~3);
 182.614 +                                        return;
 182.615 +                                }
 182.616 +                                if (!(segdat[2]&0x8000))
 182.617 +                                {
 182.618 +                                        x86np("Load CS JMP from call gate not present\n", seg & 0xfffc);
 182.619 +                                        return;
 182.620 +                                }
 182.621 +
 182.622 +
 182.623 +                                switch (segdat[2]&0x1F00)
 182.624 +                                {
 182.625 +                                        case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming code*/
 182.626 +                                        if (DPL > CPL)
 182.627 +                                        {
 182.628 +                                                pclog("Call gate DPL > CPL");
 182.629 +                                                x86gpf(NULL,seg2&~3);
 182.630 +                                                return;
 182.631 +                                        }
 182.632 +                                        case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
 182.633 +                                        CS=seg2;
 182.634 +                                        _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
 182.635 +                                        if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
 182.636 +                                        _cs.base=segdat[1];
 182.637 +                                        _cs.base|=((segdat[2]&0xFF)<<16);
 182.638 +                                        if (is386) _cs.base|=((segdat[3]>>8)<<24);
 182.639 +                                        _cs.access=segdat[2]>>8;
 182.640 +                                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.641 +                                        use32=(segdat[3]&0x40)?0x300:0;
 182.642 +                                                pc=newpc;
 182.643 +
 182.644 +#ifdef CS_ACCESSED                                                
 182.645 +                                        cpl_override = 1;
 182.646 +                                        writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
 182.647 +                                        cpl_override = 0;
 182.648 +#endif
 182.649 +                                        break;
 182.650 +
 182.651 +                                        default:
 182.652 +                                        pclog("JMP Call gate bad segment type\n");
 182.653 +                                        x86gpf(NULL,seg2&~3);
 182.654 +                                        return;
 182.655 +                                }
 182.656 +                                break;
 182.657 +
 182.658 +                                
 182.659 +                                case 0x900: /*386 Task gate*/
 182.660 +                                pc=oxpc;
 182.661 +                                cpl_override=1;
 182.662 +                                taskswitch286(seg,segdat,segdat[2]&0x800);
 182.663 +                                cpl_override=0;
 182.664 +//                                case 0xB00: /*386 Busy task gate*/
 182.665 +//                                if (optype==JMP) pclog("Task switch!\n");
 182.666 +//                                taskswitch386(seg,segdat);
 182.667 +                                return;
 182.668 +
 182.669 +                                default:
 182.670 +                                pclog("Bad JMP CS %02X %02X %i special descriptor %03X %04X\n",opcode,rmdat,optype,segdat[2]&0xF00,seg);
 182.671 +                                x86gpf(NULL,0);
 182.672 +                                return;
 182.673 +//                                dumpregs();
 182.674 +//                                exit(-1);
 182.675 +                        }
 182.676 +                }
 182.677 +//                pclog("CS = %04X base=%06X limit=%04X access=%02X  %04X\n",CS,cs,_cs.limit,_cs.access,addr);
 182.678 +//                dumpregs();
 182.679 +//                exit(-1);
 182.680 +        }
 182.681 +        else
 182.682 +        {
 182.683 +                _cs.base=seg<<4;
 182.684 +                _cs.limit=0xFFFF;
 182.685 +                CS=seg;
 182.686 +                if (eflags&VM_FLAG) _cs.access=3<<5;
 182.687 +                else                _cs.access=0<<5;
 182.688 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.689 +        }
 182.690 +}
 182.691 +
 182.692 +void PUSHW(uint16_t v)
 182.693 +{
 182.694 +//        if (output==3) pclog("PUSHW %04X to %08X\n",v,ESP-4);
 182.695 +        if (stack32)
 182.696 +        {
 182.697 +                writememw(ss,ESP-2,v);
 182.698 +                if (abrt) return;
 182.699 +                ESP-=2;
 182.700 +        }
 182.701 +        else
 182.702 +        {
 182.703 +//                pclog("Write %04X to %08X\n", v, ss+((SP-2)&0xFFFF));
 182.704 +                writememw(ss,((SP-2)&0xFFFF),v);
 182.705 +                if (abrt) return;
 182.706 +                SP-=2;
 182.707 +        }
 182.708 +}
 182.709 +void PUSHL(uint32_t v)
 182.710 +{
 182.711 +//        if (output==3) pclog("PUSHL %08X to %08X\n",v,ESP-4);
 182.712 +        if (stack32)
 182.713 +        {
 182.714 +                writememl(ss,ESP-4,v);
 182.715 +                if (abrt) return;
 182.716 +                ESP-=4;
 182.717 +        }
 182.718 +        else
 182.719 +        {
 182.720 +                writememl(ss,((SP-4)&0xFFFF),v);
 182.721 +                if (abrt) return;
 182.722 +                SP-=4;
 182.723 +        }
 182.724 +}
 182.725 +uint16_t POPW()
 182.726 +{
 182.727 +        uint16_t tempw;
 182.728 +        if (stack32)
 182.729 +        {
 182.730 +                tempw=readmemw(ss,ESP);
 182.731 +                if (abrt) return 0;
 182.732 +                ESP+=2;
 182.733 +        }
 182.734 +        else
 182.735 +        {
 182.736 +                tempw=readmemw(ss,SP);
 182.737 +                if (abrt) return 0;
 182.738 +                SP+=2;
 182.739 +        }
 182.740 +        return tempw;
 182.741 +}
 182.742 +uint32_t POPL()
 182.743 +{
 182.744 +        uint32_t templ;
 182.745 +        if (stack32)
 182.746 +        {
 182.747 +                templ=readmeml(ss,ESP);
 182.748 +                if (abrt) return 0;
 182.749 +                ESP+=4;
 182.750 +        }
 182.751 +        else
 182.752 +        {
 182.753 +                templ=readmeml(ss,SP);
 182.754 +                if (abrt) return 0;
 182.755 +                SP+=4;
 182.756 +        }
 182.757 +        return templ;
 182.758 +}
 182.759 +
 182.760 +void loadcscall(uint16_t seg)
 182.761 +{
 182.762 +        uint16_t seg2;
 182.763 +        uint16_t segdat[4],segdat2[4],newss;
 182.764 +        uint32_t addr,oldssbase=ss, oaddr;
 182.765 +        uint32_t newpc;
 182.766 +        int count;
 182.767 +        uint16_t oldcs=CPL;
 182.768 +        uint32_t oldss,oldsp,newsp,oldpc, oldsp2;
 182.769 +        int type;
 182.770 +        uint16_t tempw;
 182.771 +        
 182.772 +        int csout = output;
 182.773 +        
 182.774 +        if (msw&1 && !(eflags&VM_FLAG))
 182.775 +        {
 182.776 +                //flushmmucache();
 182.777 +                if (csout) pclog("Protected mode CS load! %04X\n",seg);
 182.778 +                if (!(seg&~3))
 182.779 +                {
 182.780 +                        pclog("Trying to load CS with NULL selector! lcscall\n");
 182.781 +                        x86gpf(NULL,0);
 182.782 +                        return;
 182.783 +//                        dumpregs();
 182.784 +//                        exit(-1);
 182.785 +                }
 182.786 +                addr=seg&~7;
 182.787 +                if (seg&4)
 182.788 +                {
 182.789 +                        if (addr>=ldt.limit)
 182.790 +                        {
 182.791 +                                pclog("Bigger than LDT limit %04X %04X CSC\n",seg,gdt.limit);
 182.792 +                                x86gpf(NULL,seg&~3);
 182.793 +                                return;
 182.794 +                        }
 182.795 +                        addr+=ldt.base;
 182.796 +                }
 182.797 +                else
 182.798 +                {
 182.799 +                        if (addr>=gdt.limit)
 182.800 +                        {
 182.801 +                                pclog("Bigger than GDT limit %04X %04X CSC\n",seg,gdt.limit);
 182.802 +                                x86gpf(NULL,seg&~3);
 182.803 +                                return;
 182.804 +                        }
 182.805 +                        addr+=gdt.base;
 182.806 +                }
 182.807 +                cpl_override=1;
 182.808 +                segdat[0]=readmemw(0,addr);
 182.809 +                segdat[1]=readmemw(0,addr+2);
 182.810 +                segdat[2]=readmemw(0,addr+4);
 182.811 +                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.812 +                type=segdat[2]&0xF00;
 182.813 +                if (type==0x400) newpc=segdat[0];
 182.814 +                else             newpc=segdat[0]|(segdat[3]<<16);
 182.815 +
 182.816 +                if (csout) pclog("Code seg call - %04X - %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2]);
 182.817 +                if (segdat[2]&0x1000)
 182.818 +                {
 182.819 +                        if (!(segdat[2]&0x400)) /*Not conforming*/
 182.820 +                        {
 182.821 +                                if ((seg&3)>CPL)
 182.822 +                                {
 182.823 +                                        if (csout) pclog("Not conforming, RPL > CPL\n");
 182.824 +                                        x86gpf(NULL,seg&~3);
 182.825 +                                        return;
 182.826 +                                }
 182.827 +                                if (CPL != DPL)
 182.828 +                                {
 182.829 +                                        if (csout) pclog("Not conforming, CPL != DPL (%i %i)\n",CPL,DPL);
 182.830 +                                        x86gpf(NULL,seg&~3);
 182.831 +                                        return;
 182.832 +                                }
 182.833 +                        }
 182.834 +                        if (CPL < DPL)
 182.835 +                        {
 182.836 +                                if (csout) pclog("CPL < DPL\n");
 182.837 +                                x86gpf(NULL,seg&~3);
 182.838 +                                return;
 182.839 +                        }
 182.840 +                        if (!(segdat[2]&0x8000))
 182.841 +                        {
 182.842 +                                if (csout) pclog("Not present\n");
 182.843 +                                x86np("Load CS call not present", seg & 0xfffc);
 182.844 +                                return;
 182.845 +                        }
 182.846 +                        if (segdat[3]&0x40) use32=0x300;
 182.847 +                        else                use32=0;
 182.848 +
 182.849 +#ifdef CS_ACCESSED                        
 182.850 +                        cpl_override = 1;
 182.851 +                        writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
 182.852 +                        cpl_override = 0;
 182.853 +#endif
 182.854 +                        
 182.855 +                        /*Conforming segments don't change CPL, so preserve existing CPL*/
 182.856 +                        if (segdat[2]&0x400)
 182.857 +                        {
 182.858 +                                seg = (seg & ~3) | CPL;
 182.859 +                                segdat[2] = (segdat[2] & ~(3 << 5+8)) | (CPL << 5+8);
 182.860 +                        }
 182.861 +                        else /*On non-conforming segments, set RPL = CPL*/
 182.862 +                                seg = (seg & ~3) | CPL;
 182.863 +                        CS=seg;
 182.864 +                        _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
 182.865 +                        if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
 182.866 +                        _cs.base=segdat[1];
 182.867 +                        _cs.base|=((segdat[2]&0xFF)<<16);
 182.868 +                        if (is386) _cs.base|=((segdat[3]>>8)<<24);
 182.869 +                        _cs.access=segdat[2]>>8;
 182.870 +                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
 182.871 +                        use32=(segdat[3]&0x40)?0x300:0;
 182.872 +                        if (csout) pclog("Complete\n");
 182.873 +                }
 182.874 +                else
 182.875 +                {
 182.876 +                        type=segdat[2]&0xF00;
 182.877 +                        if (csout) pclog("Type %03X\n",type);
 182.878 +                        switch (type)
 182.879 +                        {
 182.880 +                                case 0x400: /*Call gate*/
 182.881 +                                case 0xC00: /*386 Call gate*/
 182.882 +                                if (output) pclog("Callgate %08X\n", pc);
 182.883 +                                cgate32=(type&0x800);
 182.884 +                                cgate16=!cgate32;
 182.885 +                                oldcs=CS;
 182.886 +                                oldpc=pc;
 182.887 +                                count=segdat[2]&31;
 182.888 +                                if ((DPL < CPL) || (DPL < (seg&3)))
 182.889 +                                {
 182.890 +                                        x86gpf(NULL,seg&~3);
 182.891 +                                        return;
 182.892 +                                }
 182.893 +                                if (!(segdat[2]&0x8000))
 182.894 +                                {
 182.895 +                                        if (output) pclog("Call gate not present %04X\n",seg);
 182.896 +                                        x86np("Call gate not present\n", seg & 0xfffc);
 182.897 +                                        return;
 182.898 +                                }
 182.899 +                                seg2=segdat[1];
 182.900 +                                
 182.901 +                                if (output) pclog("New address : %04X:%08X\n", seg2, newpc);
 182.902 +                                
 182.903 +                                if (!(seg2&~3))
 182.904 +                                {
 182.905 +                                        pclog("Trying to load CS with NULL selector! lcscallcg\n");
 182.906 +                                        x86gpf(NULL,0);
 182.907 +                                        return;
 182.908 +//                                        dumpregs();
 182.909 +//                                       exit(-1);
 182.910 +                                }
 182.911 +                                addr=seg2&~7;
 182.912 +                                if (seg2&4)
 182.913 +                                {
 182.914 +                                        if (addr>=ldt.limit)
 182.915 +                                        {
 182.916 +                                                pclog("Bigger than LDT limit %04X %04X CSC\n",seg2,gdt.limit);
 182.917 +                                                x86gpf(NULL,seg2&~3);
 182.918 +                                                return;
 182.919 +                                        }
 182.920 +                                        addr+=ldt.base;
 182.921 +                                }
 182.922 +                                else
 182.923 +                                {
 182.924 +                                        if (addr>=gdt.limit)
 182.925 +                                        {
 182.926 +                                                pclog("Bigger than GDT limit %04X %04X CSC\n",seg2,gdt.limit);
 182.927 +                                                x86gpf(NULL,seg2&~3);
 182.928 +                                                return;
 182.929 +                                        }
 182.930 +                                        addr+=gdt.base;
 182.931 +                                }
 182.932 +                                cpl_override=1;
 182.933 +                                segdat[0]=readmemw(0,addr);
 182.934 +                                segdat[1]=readmemw(0,addr+2);
 182.935 +                                segdat[2]=readmemw(0,addr+4);
 182.936 +                                segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
 182.937 +                                
 182.938 +                                if (output) pclog("Code seg2 call - %04X - %04X %04X %04X\n",seg2,segdat[0],segdat[1],segdat[2]);
 182.939 +                                
 182.940 +                                if (DPL > CPL)
 182.941 +                                {
 182.942 +                                        x86gpf(NULL,seg2&~3);
 182.943 +                                        return;
 182.944 +                                }
 182.945 +                                if (!(segdat[2]&0x8000))
 182.946 +                                {
 182.947 +                                        if (output) pclog("Call gate CS not present %04X\n",seg2);
 182.948 +                                        x86np("Call gate CS not present", seg2 & 0xfffc);
 182.949 +                                        return;
 182.950 +                                }
 182.951 +
 182.952 +                                
 182.953 +                                switch (segdat[2]&0x1F00)
 182.954 +                                {
 182.955 +                                        case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming code*/
 182.956 +                                        if (DPL < CPL)
 182.957 +                                        {
 182.958 +                                                oaddr = addr;
 182.959 +                                                /*Load new stack*/
 182.960 +                                                oldss=SS;
 182.961 +                                                oldsp=oldsp2=ESP;
 182.962 +                                                cpl_override=1;
 182.963 +                                                if (tr.access&8)
 182.964 +                                                {
 182.965 +                                                        addr = 4 + tr.base + (DPL * 8);
 182.966 +                                                        newss=readmemw(0,addr+4);
 182.967 +                                                        newsp=readmeml(0,addr);
 182.968 +                                                }
 182.969 +                                                else
 182.970 +                                                {
 182.971 +                                                        addr = 2 + tr.base + (DPL * 4);
 182.972 +                                                        newss=readmemw(0,addr+2);
 182.973 +                                                        newsp=readmemw(0,addr);
 182.974 +                                                }
 182.975 +                                                cpl_override=0;
 182.976 +                                                if (abrt) return;
 182.977 +                                                if (output) pclog("New stack %04X:%08X\n",newss,newsp);
 182.978 +                                                if (!(newss&~3))
 182.979 +                                                {
 182.980 +                                                        pclog("Call gate loading null SS\n");
 182.981 +                                                        x86ts(NULL,newss&~3);
 182.982 +                                                        return;
 182.983 +                                                }
 182.984 +                                                addr=newss&~7;
 182.985 +                                                if (newss&4)
 182.986 +                                                {
 182.987 +                                                        if (addr>=ldt.limit)
 182.988 +                                                        {
 182.989 +                                                                x86abort("Bigger than LDT limit %04X %08X %04X CSC SS\n",newss,addr,ldt.limit);
 182.990 +                                                                x86ts(NULL,newss&~3);
 182.991 +                                                                return;
 182.992 +                                                        }
 182.993 +                                                        addr+=ldt.base;
 182.994 +                                                }
 182.995 +                                                else
 182.996 +                                                {
 182.997 +                                                        if (addr>=gdt.limit)
 182.998 +                                                        {
 182.999 +                                                                x86abort("Bigger than GDT limit %04X %04X CSC\n",newss,gdt.limit);
182.1000 +                                                                x86ts(NULL,newss&~3);
182.1001 +                                                                return;
182.1002 +                                                        }
182.1003 +                                                        addr+=gdt.base;
182.1004 +                                                }
182.1005 +                                                cpl_override=1;
182.1006 +                                                if (output) pclog("Read stack seg\n");
182.1007 +                                                segdat2[0]=readmemw(0,addr);
182.1008 +                                                segdat2[1]=readmemw(0,addr+2);
182.1009 +                                                segdat2[2]=readmemw(0,addr+4);
182.1010 +                                                segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
182.1011 +                                                if (output) pclog("Read stack seg done!\n");
182.1012 +                                                if (((newss & 3) != DPL) || (DPL2 != DPL))
182.1013 +                                                {
182.1014 +                                                        pclog("Call gate loading SS with wrong permissions  %04X %04X  %i %i   %04X %04X\n", newss, seg2, DPL, DPL2, segdat[2], segdat2[2]);
182.1015 +//                                                        dumpregs();
182.1016 +//                                                        exit(-1);
182.1017 +                                                        x86ts(NULL,newss&~3);
182.1018 +                                                        return;
182.1019 +                                                }
182.1020 +                                                if ((segdat2[2]&0x1A00)!=0x1200)
182.1021 +                                                {
182.1022 +                                                        pclog("Call gate loading SS wrong type\n");
182.1023 +                                                        x86ts(NULL,newss&~3);
182.1024 +                                                        return;
182.1025 +                                                }
182.1026 +                                                if (!(segdat2[2]&0x8000))
182.1027 +                                                {
182.1028 +                                                        pclog("Call gate loading SS not present\n");
182.1029 +                                                        x86np("Call gate loading SS not present\n", newss & 0xfffc);
182.1030 +                                                        return;
182.1031 +                                                }
182.1032 +                                                if (!stack32) oldsp &= 0xFFFF;
182.1033 +                                                SS=newss;
182.1034 +                                                stack32=segdat2[3]&0x40;
182.1035 +                                                if (stack32) ESP=newsp;
182.1036 +                                                else         SP=newsp;
182.1037 +                                                _ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
182.1038 +                                                if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
182.1039 +                                                if ((segdat2[2]>>8) & 4)
182.1040 +                                                   _ss.limit = 0xffffffff;
182.1041 +
182.1042 +                                                _ss.limitw=(segdat2[2]&0x200)?1:0;
182.1043 +                                                _ss.base=segdat2[1];
182.1044 +                                                _ss.base|=((segdat2[2]&0xFF)<<16);
182.1045 +                                                if (is386) _ss.base|=((segdat2[3]>>8)<<24);
182.1046 +                                                _ss.access=segdat2[2]>>8;
182.1047 +
182.1048 +                                                if (output) pclog("Set access 1\n");
182.1049 +
182.1050 +#ifdef SEL_ACCESSED                                                
182.1051 +                                                cpl_override = 1;
182.1052 +                                                writememw(0, addr+4, segdat2[2] | 0x100); /*Set accessed bit*/
182.1053 +                                                cpl_override = 0;
182.1054 +#endif
182.1055 +                                                
182.1056 +                                                CS=seg2;
182.1057 +                                                _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.1058 +                                                if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.1059 +                                                _cs.base=segdat[1];
182.1060 +                                                _cs.base|=((segdat[2]&0xFF)<<16);
182.1061 +                                                if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.1062 +                                                _cs.access=segdat[2]>>8;
182.1063 +                                                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1064 +                                                use32=(segdat[3]&0x40)?0x300:0;
182.1065 +                                                pc=newpc;
182.1066 +                                                
182.1067 +                                                if (output) pclog("Set access 2\n");
182.1068 +                                                
182.1069 +#ifdef CS_ACCESSED
182.1070 +                                                cpl_override = 1;
182.1071 +                                                writememw(0, oaddr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.1072 +                                                cpl_override = 0;
182.1073 +#endif
182.1074 +                        
182.1075 +                                                if (output) pclog("Type %04X\n",type);
182.1076 +                                                if (type==0xC00)
182.1077 +                                                {
182.1078 +                                                        PUSHL(oldss);
182.1079 +                                                        PUSHL(oldsp2);
182.1080 +                                                        if (abrt)
182.1081 +                                                        {
182.1082 +                                                                pclog("ABRT PUSHL\n");
182.1083 +                                                                SS = oldss;
182.1084 +                                                                ESP = oldsp2;
182.1085 +                                                                return;
182.1086 +                                                        }
182.1087 +//                                                        if (output) pclog("Stack now %04X:%08X\n",SS,ESP);
182.1088 +                                                        if (count)
182.1089 +                                                        {
182.1090 +                                                                while (count)
182.1091 +                                                                {
182.1092 +                                                                        count--;
182.1093 +                                                                        PUSHL(readmeml(oldssbase,oldsp+(count*4)));
182.1094 +                                                                        if (abrt)
182.1095 +                                                                        {
182.1096 +                                                                                pclog("ABRT COPYL\n");
182.1097 +                                                                                SS = oldss;
182.1098 +                                                                                ESP = oldsp2;
182.1099 +                                                                                return;
182.1100 +                                                                        }
182.1101 +                                                                }
182.1102 +                                                        }
182.1103 +//                                                                x86abort("Call gate with count %i\n",count);
182.1104 +//                                                        PUSHL(oldcs);
182.1105 +//                                                        PUSHL(oldpc); if (abrt) return;
182.1106 +                                                }
182.1107 +                                                else
182.1108 +                                                {
182.1109 +                                                        if (output) pclog("Stack %04X\n",SP);
182.1110 +                                                        PUSHW(oldss);
182.1111 +                                                        if (output) pclog("Write SS to %04X:%04X\n",SS,SP);
182.1112 +                                                        PUSHW(oldsp2);
182.1113 +                                                        if (abrt)
182.1114 +                                                        {
182.1115 +                                                                pclog("ABRT PUSHW\n");
182.1116 +                                                                SS = oldss;
182.1117 +                                                                ESP = oldsp2;
182.1118 +                                                                return;
182.1119 +                                                        }
182.1120 +                                                        if (output) pclog("Write SP to %04X:%04X\n",SS,SP);
182.1121 +//                                                        if (output) pclog("Stack %04X %i %04X:%04X\n",SP,count,oldssbase,oldsp);
182.1122 +//                                                        if (output) pclog("PUSH %04X %04X %i %i now %04X:%08X\n",oldss,oldsp,count,stack32,SS,ESP);
182.1123 +                                                        if (count)
182.1124 +                                                        {
182.1125 +                                                                while (count)
182.1126 +                                                                {
182.1127 +                                                                        count--;
182.1128 +                                                                        tempw=readmemw(oldssbase,(oldsp&0xFFFF)+(count*2));
182.1129 +                                                                        if (output) pclog("PUSH %04X\n",tempw);
182.1130 +                                                                        PUSHW(tempw);
182.1131 +                                                                        if (abrt)
182.1132 +                                                                        {
182.1133 +                                                                                pclog("ABRT COPYW\n");
182.1134 +                                                                                SS = oldss;
182.1135 +                                                                                ESP = oldsp2;
182.1136 +                                                                                return;
182.1137 +                                                                        }
182.1138 +                                                                }
182.1139 +                                                        }
182.1140 +//                                                        if (output) pclog("Stack %04X\n",SP);
182.1141 +//                                                        if (count) x86abort("Call gate with count\n");
182.1142 +//                                                        PUSHW(oldcs);
182.1143 +//                                                       PUSHW(oldpc); if (abrt) return;
182.1144 +                                                }
182.1145 +                                                break;
182.1146 +                                        }
182.1147 +                                        else if (DPL > CPL)
182.1148 +                                        {
182.1149 +                                                pclog("Call gate DPL > CPL");
182.1150 +                                                x86gpf(NULL,seg2&~3);
182.1151 +                                                return;
182.1152 +                                        }
182.1153 +                                        case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
182.1154 +/*                                        if (type==0xC00)
182.1155 +                                        {
182.1156 +                                                PUSHL(oldcs);
182.1157 +                                                PUSHL(oldpc); if (abrt) return;
182.1158 +                                        }
182.1159 +                                        else
182.1160 +                                        {
182.1161 +                                                PUSHW(oldcs);
182.1162 +                                                PUSHW(oldpc); if (abrt) return;
182.1163 +                                        }*/
182.1164 +                                        CS=seg2;
182.1165 +                                        _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.1166 +                                        if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.1167 +                                        _cs.base=segdat[1];
182.1168 +                                        _cs.base|=((segdat[2]&0xFF)<<16);
182.1169 +                                        if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.1170 +                                        _cs.access=segdat[2]>>8;
182.1171 +                                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1172 +                                        use32=(segdat[3]&0x40)?0x300:0;
182.1173 +                                                pc=newpc;
182.1174 +
182.1175 +#ifdef CS_ACCESSED                                                
182.1176 +                                        cpl_override = 1;
182.1177 +                                        writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.1178 +                                        cpl_override = 0;
182.1179 +#endif
182.1180 +                                        break;
182.1181 +                                        
182.1182 +                                        default:
182.1183 +                                        pclog("Call gate bad segment type\n");
182.1184 +                                        x86gpf(NULL,seg2&~3);
182.1185 +                                        return;
182.1186 +                                }
182.1187 +                                break;
182.1188 +
182.1189 +//                                case 0x900: /*386 Task gate*/
182.1190 +//                                case 0xB00: /*386 Busy task gate*/
182.1191 +//                                if (optype==JMP) pclog("Task switch!\n");
182.1192 +//                                taskswitch386(seg,segdat);
182.1193 +//                                return;
182.1194 +
182.1195 +
182.1196 +                                default:
182.1197 +                                pclog("Bad CALL special descriptor %03X\n",segdat[2]&0xF00);
182.1198 +                                x86gpf(NULL,seg&~3);
182.1199 +                                return;
182.1200 +//                                dumpregs();
182.1201 +//                                exit(-1);
182.1202 +                        }
182.1203 +                }
182.1204 +//                pclog("CS = %04X base=%06X limit=%04X access=%02X  %04X\n",CS,cs,_cs.limit,_cs.access,addr);
182.1205 +//                dumpregs();
182.1206 +//                exit(-1);
182.1207 +        }
182.1208 +        else
182.1209 +        {
182.1210 +                _cs.base=seg<<4;
182.1211 +                _cs.limit=0xFFFF;
182.1212 +                CS=seg;
182.1213 +                if (eflags&VM_FLAG) _cs.access=3<<5;
182.1214 +                else                _cs.access=0<<5;
182.1215 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1216 +        }
182.1217 +}
182.1218 +
182.1219 +void pmoderetf(int is32, uint16_t off)
182.1220 +{
182.1221 +        uint32_t newpc;
182.1222 +        uint32_t newsp;
182.1223 +        uint32_t addr, oaddr;
182.1224 +        uint16_t segdat[4],segdat2[4],seg,newss;
182.1225 +        uint32_t oldsp=ESP;
182.1226 +        if (output) pclog("RETF %i %04X:%04X  %08X %04X\n",is32,CS,pc,cr0,eflags);
182.1227 +        if (is32)
182.1228 +        {
182.1229 +                newpc=POPL();
182.1230 +                seg=POPL(); if (abrt) return;
182.1231 +        }
182.1232 +        else
182.1233 +        {
182.1234 +                if (output) pclog("PC read from %04X:%04X\n",SS,SP);
182.1235 +                newpc=POPW();
182.1236 +                if (output) pclog("CS read from %04X:%04X\n",SS,SP);
182.1237 +                seg=POPW(); if (abrt) return;
182.1238 +        }
182.1239 +        if (output) pclog("Return to %04X:%08X\n",seg,newpc);
182.1240 +        if ((seg&3)<CPL)
182.1241 +        {
182.1242 +                pclog("RETF RPL<CPL %04X %i %i %04X:%08X\n",seg,CPL,ins,CS,pc);
182.1243 +//                output=3;
182.1244 +//                timetolive=100;
182.1245 +//                dumpregs();
182.1246 +//                exit(-1);
182.1247 +                ESP=oldsp;
182.1248 +                x86gpf(NULL,seg&~3);
182.1249 +                return;
182.1250 +        }
182.1251 +        if (!(seg&~3))
182.1252 +        {
182.1253 +                pclog("Trying to load CS with NULL selector! retf\n");
182.1254 +//                dumpregs();
182.1255 +//                exit(-1);
182.1256 +                x86gpf(NULL,0);
182.1257 +                return;
182.1258 +        }
182.1259 +        addr=seg&~7;
182.1260 +        if (seg&4)
182.1261 +        {
182.1262 +                if (addr>=ldt.limit)
182.1263 +                {
182.1264 +                        pclog("Bigger than LDT limit %04X %04X RETF\n",seg,ldt.limit);
182.1265 +                        x86gpf(NULL,seg&~3);
182.1266 +                        return;
182.1267 +                }
182.1268 +                addr+=ldt.base;
182.1269 +        }
182.1270 +        else
182.1271 +        {
182.1272 +                if (addr>=gdt.limit)
182.1273 +                {
182.1274 +                        pclog("Bigger than GDT limit %04X %04X RETF\n",seg,gdt.limit);
182.1275 +                        x86gpf(NULL,seg&~3);
182.1276 +//                        dumpregs();
182.1277 +//                        exit(-1);
182.1278 +                        return;
182.1279 +                }
182.1280 +                addr+=gdt.base;
182.1281 +        }
182.1282 +        cpl_override=1;
182.1283 +        segdat[0]=readmemw(0,addr);
182.1284 +        segdat[1]=readmemw(0,addr+2);
182.1285 +        segdat[2]=readmemw(0,addr+4);
182.1286 +        segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) { ESP=oldsp; return; }
182.1287 +        oaddr = addr;
182.1288 +        
182.1289 +        if (output) pclog("CPL %i RPL %i %i\n",CPL,seg&3,is32);
182.1290 +
182.1291 +        if (stack32) ESP+=off;
182.1292 +        else         SP+=off;
182.1293 +
182.1294 +        if (CPL==(seg&3))
182.1295 +        {
182.1296 +                if (output) pclog("RETF CPL = RPL  %04X\n", segdat[2]);
182.1297 +                switch (segdat[2]&0x1F00)
182.1298 +                {
182.1299 +                        case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/
182.1300 +                        if (CPL != DPL)
182.1301 +                        {
182.1302 +                                pclog("RETF non-conforming CPL != DPL\n");
182.1303 +                                ESP=oldsp;
182.1304 +                                x86gpf(NULL,seg&~3);
182.1305 +                                return;
182.1306 +                        }
182.1307 +                        break;
182.1308 +                        case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
182.1309 +                        if (CPL < DPL)
182.1310 +                        {
182.1311 +                                pclog("RETF non-conforming CPL < DPL\n");
182.1312 +                                ESP=oldsp;
182.1313 +                                x86gpf(NULL,seg&~3);
182.1314 +                                return;
182.1315 +                        }
182.1316 +                        break;
182.1317 +                        default:
182.1318 +                        pclog("RETF CS not code segment\n");
182.1319 +                        x86gpf(NULL,seg&~3);
182.1320 +                        return;
182.1321 +                }
182.1322 +                if (!(segdat[2]&0x8000))
182.1323 +                {
182.1324 +                        pclog("RETF CS not present %i  %04X %04X %04X\n",ins, segdat[0], segdat[1], segdat[2]);
182.1325 +                        ESP=oldsp;
182.1326 +                        x86np("RETF CS not present\n", seg & 0xfffc);
182.1327 +                        return;
182.1328 +                }
182.1329 +                
182.1330 +#ifdef CS_ACCESSED
182.1331 +                cpl_override = 1;
182.1332 +                writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.1333 +                cpl_override = 0;
182.1334 +#endif
182.1335 +                                
182.1336 +                pc=newpc;
182.1337 +                if (segdat[2] & 0x400)
182.1338 +                   segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8);
182.1339 +                CS = seg;
182.1340 +                _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.1341 +                if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.1342 +                _cs.base=segdat[1];
182.1343 +                _cs.base|=((segdat[2]&0xFF)<<16);
182.1344 +                if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.1345 +                _cs.access=segdat[2]>>8;
182.1346 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1347 +                use32=(segdat[3]&0x40)?0x300:0;
182.1348 +                
182.1349 +//                pclog("CPL=RPL return to %04X:%08X\n",CS,pc);
182.1350 +        }
182.1351 +        else
182.1352 +        {
182.1353 +                switch (segdat[2]&0x1F00)
182.1354 +                {
182.1355 +                        case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/
182.1356 +                        if ((seg&3) != DPL)
182.1357 +                        {
182.1358 +                                pclog("RETF non-conforming RPL != DPL\n");
182.1359 +                                ESP=oldsp;
182.1360 +                                x86gpf(NULL,seg&~3);
182.1361 +                                return;
182.1362 +                        }
182.1363 +                        if (output) pclog("RETF non-conforming, %i %i\n",seg&3, DPL);
182.1364 +                        break;
182.1365 +                        case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
182.1366 +                        if ((seg&3) < DPL)
182.1367 +                        {
182.1368 +                                pclog("RETF non-conforming RPL < DPL\n");
182.1369 +                                ESP=oldsp;
182.1370 +                                x86gpf(NULL,seg&~3);
182.1371 +                                return;
182.1372 +                        }
182.1373 +                        if (output) pclog("RETF conforming, %i %i\n",seg&3, DPL);
182.1374 +                        break;
182.1375 +                        default:
182.1376 +                        pclog("RETF CS not code segment\n");
182.1377 +                        ESP=oldsp;
182.1378 +                        x86gpf(NULL,seg&~3);
182.1379 +                        return;
182.1380 +                }
182.1381 +                if (!(segdat[2]&0x8000))
182.1382 +                {
182.1383 +                        pclog("RETF CS not present! %i  %04X %04X %04X\n",ins, segdat[0], segdat[1], segdat[2]);
182.1384 +
182.1385 +                        ESP=oldsp;
182.1386 +                        x86np("RETF CS not present\n", seg & 0xfffc);
182.1387 +                        return;
182.1388 +                }
182.1389 +                if (is32)
182.1390 +                {
182.1391 +                        newsp=POPL();
182.1392 +                        newss=POPL(); if (abrt) return;
182.1393 +//                        pclog("is32 new stack %04X:%04X\n",newss,newsp);
182.1394 +                }
182.1395 +                else
182.1396 +                {
182.1397 +                        if (output) pclog("SP read from %04X:%04X\n",SS,SP);
182.1398 +                        newsp=POPW();
182.1399 +                        if (output) pclog("SS read from %04X:%04X\n",SS,SP);
182.1400 +                        newss=POPW(); if (abrt) return;
182.1401 +//                        pclog("!is32 new stack %04X:%04X\n",newss,newsp);
182.1402 +                }
182.1403 +                if (output) pclog("Read new stack : %04X:%04X (%08X)\n", newss, newsp, ldt.base);
182.1404 +                if (!(newss&~3))
182.1405 +                {
182.1406 +                        pclog("RETF loading null SS\n");
182.1407 +                        ESP=oldsp;
182.1408 +                        x86gpf(NULL,newss&~3);
182.1409 +                        return;
182.1410 +                }
182.1411 +                addr=newss&~7;
182.1412 +                if (newss&4)
182.1413 +                {
182.1414 +                        if (addr>=ldt.limit)
182.1415 +                        {
182.1416 +                                pclog("Bigger than LDT limit %04X %04X RETF SS\n",newss,gdt.limit);
182.1417 +                                ESP=oldsp;
182.1418 +                                x86gpf(NULL,newss&~3);
182.1419 +                                return;
182.1420 +                        }
182.1421 +                        addr+=ldt.base;
182.1422 +                }
182.1423 +                else
182.1424 +                {
182.1425 +                        if (addr>=gdt.limit)
182.1426 +                        {
182.1427 +                                pclog("Bigger than GDT limit %04X %04X RETF SS\n",newss,gdt.limit);
182.1428 +                                ESP=oldsp;
182.1429 +                                x86gpf(NULL,newss&~3);
182.1430 +                                return;
182.1431 +                        }
182.1432 +                        addr+=gdt.base;
182.1433 +                }
182.1434 +                cpl_override=1;
182.1435 +                segdat2[0]=readmemw(0,addr);
182.1436 +                segdat2[1]=readmemw(0,addr+2);
182.1437 +                segdat2[2]=readmemw(0,addr+4);
182.1438 +                segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) { ESP=oldsp; return; }
182.1439 +                if (output) pclog("Segment data %04X %04X %04X %04X\n", segdat2[0], segdat2[1], segdat2[2], segdat2[3]);
182.1440 +//                if (((newss & 3) != DPL) || (DPL2 != DPL))
182.1441 +                if ((newss & 3) != (seg & 3))
182.1442 +                {
182.1443 +                        pclog("RETF loading SS with wrong permissions %i %i  %04X %04X\n", newss & 3, seg & 3, newss, seg);
182.1444 +                        ESP=oldsp;
182.1445 +//                        output = 3;
182.1446 +//                        dumpregs();
182.1447 +//                        exit(-1);
182.1448 +                        x86gpf(NULL,newss&~3);
182.1449 +                        return;
182.1450 +                }
182.1451 +                if ((segdat2[2]&0x1A00)!=0x1200)
182.1452 +                {
182.1453 +                        pclog("RETF loading SS wrong type\n");
182.1454 +                        ESP=oldsp;
182.1455 +//                        dumpregs();
182.1456 +//                        exit(-1);
182.1457 +                        x86gpf(NULL,newss&~3);
182.1458 +                        return;
182.1459 +                }
182.1460 +                if (!(segdat2[2]&0x8000))
182.1461 +                {
182.1462 +                        pclog("RETF loading SS not present\n");
182.1463 +                        ESP=oldsp;
182.1464 +                        x86np("RETF loading SS not present\n", newss & 0xfffc);
182.1465 +                        return;
182.1466 +                }
182.1467 +                if (DPL2 != (seg & 3))
182.1468 +                {
182.1469 +                        pclog("RETF loading SS with wrong permissions2 %i %i  %04X %04X\n", DPL2, seg & 3, newss, seg);
182.1470 +                        ESP=oldsp;
182.1471 +                        x86gpf(NULL,newss&~3);
182.1472 +                        return;
182.1473 +                }
182.1474 +                SS=newss;
182.1475 +                stack32=segdat2[3]&0x40;
182.1476 +                if (stack32) ESP=newsp;
182.1477 +                else         SP=newsp;
182.1478 +                _ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
182.1479 +                if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
182.1480 +                if ((segdat2[2]>>8) & 4)
182.1481 +                   _ss.limit = 0xffffffff;
182.1482 +                _ss.limitw=(segdat2[2]&0x200)?1:0;
182.1483 +                _ss.base=segdat2[1];
182.1484 +                _ss.base|=((segdat2[2]&0xFF)<<16);
182.1485 +                if (is386) _ss.base|=((segdat2[3]>>8)<<24);
182.1486 +                _ss.access=segdat2[2]>>8;
182.1487 +
182.1488 +#ifdef SEL_ACCESSED
182.1489 +                cpl_override = 1;
182.1490 +                writememw(0, addr+4, segdat2[2] | 0x100); /*Set accessed bit*/
182.1491 +
182.1492 +#ifdef CS_ACCESSED
182.1493 +                writememw(0, oaddr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.1494 +#endif
182.1495 +                cpl_override = 0;
182.1496 +#endif                
182.1497 +                        /*Conforming segments don't change CPL, so CPL = RPL*/
182.1498 +                        if (segdat[2]&0x400)
182.1499 +                           segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8);
182.1500 +
182.1501 +                pc=newpc;
182.1502 +                CS=seg;
182.1503 +                _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.1504 +                if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.1505 +                _cs.base=segdat[1];
182.1506 +                _cs.base|=((segdat[2]&0xFF)<<16);
182.1507 +                if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.1508 +                _cs.access=segdat[2]>>8;
182.1509 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1510 +                use32=(segdat[3]&0x40)?0x300:0;
182.1511 +                
182.1512 +                if (stack32) ESP+=off;
182.1513 +                else         SP+=off;
182.1514 +//                pclog("CPL<RPL return to %04X:%08X %04X:%08X\n",CS,pc,SS,ESP);
182.1515 +        }
182.1516 +}
182.1517 +
182.1518 +void restore_stack()
182.1519 +{
182.1520 +        ss=oldss; _ss.limit=oldsslimit; _ss.limitw=oldsslimitw;
182.1521 +}
182.1522 +
182.1523 +void pmodeint(int num, int soft)
182.1524 +{
182.1525 +        uint16_t segdat[4],segdat2[4],segdat3[4];
182.1526 +        uint32_t addr, oaddr;
182.1527 +        int dpl;
182.1528 +        uint16_t oldcs=CPL,oldcs2,newss;
182.1529 +        uint32_t oldss,oldsp;
182.1530 +        uint8_t oldaccess;
182.1531 +        int type;
182.1532 +        uint32_t newsp;
182.1533 +        uint16_t seg;
182.1534 +        int v86int=eflags&VM_FLAG;
182.1535 +        int stack_changed=0;
182.1536 +//        if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc);
182.1537 +//        pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt);
182.1538 +        if (eflags&VM_FLAG && IOPL!=3 && soft)
182.1539 +        {
182.1540 +                if (output) pclog("V86 banned int\n");
182.1541 +                pclog("V86 banned int!\n");
182.1542 +                x86gpf(NULL,0);
182.1543 +                return;
182.1544 +//                dumpregs();
182.1545 +//                exit(-1);
182.1546 +        }
182.1547 +        addr=(num<<3);
182.1548 +        if (addr>=idt.limit)
182.1549 +        {
182.1550 +                if (num==8)
182.1551 +                {
182.1552 +                        /*Triple fault - reset!*/
182.1553 +                        pclog("Triple fault!\n");
182.1554 +//                        output=1;
182.1555 +                        softresetx86();
182.1556 +                }
182.1557 +                else if (num==0xD)
182.1558 +                {
182.1559 +                        pclog("Double fault!\n");
182.1560 +                        pmodeint(8,0);
182.1561 +                }
182.1562 +                else
182.1563 +                {
182.1564 +                        pclog("INT out of range\n");
182.1565 +                        x86gpf(NULL,(num*8)+2+(soft)?0:1);
182.1566 +                }
182.1567 +                if (output) pclog("addr >= IDT.limit\n");
182.1568 +                return;
182.1569 +        }
182.1570 +        addr+=idt.base;
182.1571 +        cpl_override=1;
182.1572 +        segdat[0]=readmemw(0,addr);
182.1573 +        segdat[1]=readmemw(2,addr);
182.1574 +        segdat[2]=readmemw(4,addr);
182.1575 +        segdat[3]=readmemw(6,addr); cpl_override=0; if (abrt) { pclog("Abrt reading from %08X\n",addr); return; }
182.1576 +        oaddr = addr;
182.1577 +
182.1578 +        if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]);
182.1579 +        if (!(segdat[2]&0x1F00))
182.1580 +        {
182.1581 +                //pclog("No seg\n");
182.1582 +                x86gpf(NULL,(num*8)+2);
182.1583 +                return;
182.1584 +        }
182.1585 +        if (DPL<CPL && soft)
182.1586 +        {
182.1587 +                //pclog("INT : DPL<CPL  %04X:%08X  %i %i %04X\n",CS,pc,DPL,CPL,segdat[2]);
182.1588 +                x86gpf(NULL,(num*8)+2);
182.1589 +                return;
182.1590 +        }
182.1591 +        type=segdat[2]&0x1F00;
182.1592 +//        if (output) pclog("Gate type %04X\n",type);
182.1593 +        switch (type)
182.1594 +        {
182.1595 +                case 0x600: case 0x700: case 0xE00: case 0xF00: /*Interrupt and trap gates*/
182.1596 +                        intgatesize=(type>=0x800)?32:16;
182.1597 +//                        if (output) pclog("Int gate %04X %i oldpc %04X pc %04X\n",type,intgatesize,oldpc,pc);
182.1598 +                        if (!(segdat[2]&0x8000))
182.1599 +                        {
182.1600 +                                pclog("Int gate not present\n");
182.1601 +                                x86np("Int gate not present\n", (num << 3) | 2);
182.1602 +                                return;
182.1603 +                        }
182.1604 +                        seg=segdat[1];
182.1605 +//                        pclog("Interrupt gate : %04X:%04X%04X\n",seg,segdat[3],segdat[0]);
182.1606 +                        
182.1607 +                        addr=seg&~7;
182.1608 +                        if (seg&4)
182.1609 +                        {
182.1610 +                                if (addr>=ldt.limit)
182.1611 +                                {
182.1612 +                                        pclog("Bigger than LDT limit %04X %04X INT\n",seg,gdt.limit);
182.1613 +                                        x86gpf(NULL,seg&~3);
182.1614 +                                        return;
182.1615 +                                }
182.1616 +                                addr+=ldt.base;
182.1617 +                        }
182.1618 +                        else
182.1619 +                        {
182.1620 +                                if (addr>=gdt.limit)
182.1621 +                                {
182.1622 +                                        pclog("Bigger than GDT limit %04X %04X INT %i\n",seg,gdt.limit,ins);
182.1623 +                                        x86gpf(NULL,seg&~3);
182.1624 +                                        return;
182.1625 +                                }
182.1626 +                                addr+=gdt.base;
182.1627 +                        }
182.1628 +/*                        if ((seg&3) < CPL)
182.1629 +                        {
182.1630 +                                pclog("INT to higher level\n");
182.1631 +                                x86gpf(NULL,seg&~3);
182.1632 +                                return;
182.1633 +                        }*/
182.1634 +                        cpl_override=1;
182.1635 +                        segdat2[0]=readmemw(0,addr);
182.1636 +                        segdat2[1]=readmemw(0,addr+2);
182.1637 +                        segdat2[2]=readmemw(0,addr+4);
182.1638 +                        segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
182.1639 +                        oaddr = addr;
182.1640 +                        
182.1641 +                        if (DPL2 > CPL)
182.1642 +                        {
182.1643 +                                pclog("INT to higher level 2\n");
182.1644 +                                x86gpf(NULL,seg&~3);
182.1645 +                                return;
182.1646 +                        }
182.1647 +                        //pclog("Type %04X\n",segdat2[2]);
182.1648 +                        switch (segdat2[2]&0x1F00)
182.1649 +                        {
182.1650 +                                case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/
182.1651 +                                if (DPL2<CPL)
182.1652 +                                {
182.1653 +                                        stack_changed=1;
182.1654 +                                        if (!(segdat2[2]&0x8000))
182.1655 +                                        {
182.1656 +                                                pclog("Int gate CS not present\n");
182.1657 +                                                x86np("Int gate CS not present\n", segdat[1] & 0xfffc);
182.1658 +                                                return;
182.1659 +                                        }
182.1660 +                                        if ((eflags&VM_FLAG) && DPL2)
182.1661 +                                        {
182.1662 +                                                pclog("V86 calling int gate, DPL != 0\n");
182.1663 +                                                x86gpf(NULL,segdat[1]&0xFFFC);
182.1664 +                                                return;
182.1665 +                                        }
182.1666 +                                        /*Load new stack*/
182.1667 +                                        oldss=SS;
182.1668 +                                        oldsp=ESP;
182.1669 +                                        cpl_override=1;
182.1670 +                                        if (tr.access&8)
182.1671 +                                        {
182.1672 +                                                addr = 4 + tr.base + (DPL2 * 8);
182.1673 +                                                newss=readmemw(0,addr+4);
182.1674 +                                                newsp=readmeml(0,addr);
182.1675 +                                        }
182.1676 +                                        else
182.1677 +                                        {
182.1678 +                                                addr = 2 + tr.base + (DPL2 * 8);
182.1679 +                                                newss=readmemw(0,addr+2);
182.1680 +                                                newsp=readmemw(0,addr);
182.1681 +                                        }
182.1682 +                                        cpl_override=0;
182.1683 +                                        if (!(newss&~3))
182.1684 +                                        {
182.1685 +                                                pclog("Int gate loading null SS\n");
182.1686 +                                                x86ss(NULL,newss&~3);
182.1687 +                                                return;
182.1688 +                                        }
182.1689 +                                        addr=newss&~7;
182.1690 +                                        if (newss&4)
182.1691 +                                        {
182.1692 +                                                if (addr>=ldt.limit)
182.1693 +                                                {
182.1694 +                                                        pclog("Bigger than LDT limit %04X %04X PMODEINT SS\n",newss,gdt.limit);
182.1695 +                                                        x86ss(NULL,newss&~3);
182.1696 +                                                        return;
182.1697 +                                                }
182.1698 +                                                addr+=ldt.base;
182.1699 +                                        }
182.1700 +                                        else
182.1701 +                                        {
182.1702 +                                                if (addr>=gdt.limit)
182.1703 +                                                {
182.1704 +                                                        pclog("Bigger than GDT limit %04X %04X CSC\n",newss,gdt.limit);
182.1705 +                                                        x86ss(NULL,newss&~3);
182.1706 +                                                        return;
182.1707 +                                                }
182.1708 +                                                addr+=gdt.base;
182.1709 +                                        }
182.1710 +                                        cpl_override=1;
182.1711 +                                        segdat3[0]=readmemw(0,addr);
182.1712 +                                        segdat3[1]=readmemw(0,addr+2);
182.1713 +                                        segdat3[2]=readmemw(0,addr+4);
182.1714 +                                        segdat3[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) return;
182.1715 +                                        if (((newss & 3) != DPL2) || (DPL3 != DPL2))
182.1716 +                                        {
182.1717 +                                                pclog("Int gate loading SS with wrong permissions\n");
182.1718 +                                                x86ss(NULL,newss&~3);
182.1719 +                                                return;
182.1720 +                                        }
182.1721 +                                        if ((segdat3[2]&0x1A00)!=0x1200)
182.1722 +                                        {
182.1723 +                                                pclog("Int gate loading SS wrong type\n");
182.1724 +                                                x86ss(NULL,newss&~3);
182.1725 +                                                return;
182.1726 +                                        }
182.1727 +                                        if (!(segdat3[2]&0x8000))
182.1728 +                                        {
182.1729 +                                                pclog("Int gate loading SS not present\n");
182.1730 +                                                x86np("Int gate loading SS not present\n", newss & 0xfffc);
182.1731 +                                                return;
182.1732 +                                        }
182.1733 +                                        SS=newss;
182.1734 +                                        stack32=segdat3[3]&0x40;
182.1735 +                                        if (stack32) ESP=newsp;
182.1736 +                                        else         SP=newsp;
182.1737 +                                        _ss.limit=segdat3[0]|((segdat3[3]&0xF)<<16);
182.1738 +                                        if (segdat3[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
182.1739 +                                        if ((segdat3[2]>>8) & 4)
182.1740 +                                           _ss.limit = 0xffffffff;
182.1741 +                                        _ss.limitw=(segdat3[2]&0x200)?1:0;
182.1742 +                                        _ss.base=segdat3[1];
182.1743 +                                        _ss.base|=((segdat3[2]&0xFF)<<16);
182.1744 +                                        if (is386) _ss.base|=((segdat3[3]>>8)<<24);
182.1745 +                                        _ss.access=segdat3[2]>>8;
182.1746 +
182.1747 +#ifdef CS_ACCESSED                                        
182.1748 +                                        cpl_override = 1;
182.1749 +                                        writememw(0, addr+4, segdat3[2] | 0x100); /*Set accessed bit*/
182.1750 +                                        cpl_override = 0;
182.1751 +#endif
182.1752 +                                        
182.1753 +                                        if (output) pclog("New stack %04X:%08X\n",SS,ESP);
182.1754 +                                        cpl_override=1;
182.1755 +                                        if (type>=0x800)
182.1756 +                                        {
182.1757 +//                                                if (output) pclog("Push 32 %i\n",eflags&VM_FLAG);
182.1758 +                                                if (eflags & VM_FLAG)
182.1759 +                                                {
182.1760 +                                                        PUSHL(GS);
182.1761 +                                                        PUSHL(FS);
182.1762 +                                                        PUSHL(DS);
182.1763 +                                                        PUSHL(ES); if (abrt) return;
182.1764 +                                                        loadseg(0,&_ds);
182.1765 +                                                        loadseg(0,&_es);
182.1766 +                                                        loadseg(0,&_fs);
182.1767 +                                                        loadseg(0,&_gs);
182.1768 +                                                }
182.1769 +                                                PUSHL(oldss);
182.1770 +                                                PUSHL(oldsp);
182.1771 +                                                PUSHL(flags|(eflags<<16));
182.1772 +//                                                if (soft) pclog("Pushl CS %08X\n", CS);
182.1773 +                                                PUSHL(CS);
182.1774 +//                                                if (soft) pclog("Pushl PC %08X\n", pc);                                                
182.1775 +                                                PUSHL(pc); if (abrt) return;
182.1776 +//                                                if (output) pclog("32Stack %04X:%08X\n",SS,ESP);
182.1777 +                                        }
182.1778 +                                        else
182.1779 +                                        {
182.1780 +//                                                if (output) pclog("Push 16\n");
182.1781 +                                                PUSHW(oldss);
182.1782 +                                                PUSHW(oldsp);
182.1783 +                                                PUSHW(flags);
182.1784 +//                                                if (soft) pclog("Pushw CS %04X\n", CS);                                                
182.1785 +                                                PUSHW(CS);
182.1786 +//                                                if (soft) pclog("Pushw pc %04X\n", pc);                                                
182.1787 +                                                PUSHW(pc); if (abrt) return;
182.1788 +//                                                if (output) pclog("16Stack %04X:%08X\n",SS,ESP);
182.1789 +                                        }
182.1790 +                                        cpl_override=0;
182.1791 +                                        _cs.access=0;
182.1792 +//                                        pclog("Non-confirming int gate, CS = %04X\n");
182.1793 +                                        break;
182.1794 +                                }
182.1795 +                                else if (DPL2!=CPL)
182.1796 +                                {
182.1797 +                                        pclog("Non-conforming int gate DPL != CPL\n");
182.1798 +                                        x86gpf(NULL,seg&~3);
182.1799 +                                        return;
182.1800 +                                }
182.1801 +                                case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
182.1802 +                                if (!(segdat2[2]&0x8000))
182.1803 +                                {
182.1804 +                                        pclog("Int gate CS not present\n");
182.1805 +                                        x86np("Int gate CS not present\n", segdat[1] & 0xfffc);
182.1806 +                                        return;
182.1807 +                                }
182.1808 +                                if ((eflags & VM_FLAG) && DPL2<CPL)
182.1809 +                                {
182.1810 +                                        pclog("Int gate V86 mode DPL2<CPL\n");
182.1811 +                                        x86gpf(NULL,seg&~3);
182.1812 +                                        return;
182.1813 +                                }
182.1814 +                                if (!stack_changed && ssegs) restore_stack();
182.1815 +                                if (type>0x800)
182.1816 +                                {
182.1817 +                                        PUSHL(flags|(eflags<<16));
182.1818 +//                                        if (soft) pclog("Pushlc CS %08X\n", CS);
182.1819 +                                        PUSHL(CS);
182.1820 +//                                        if (soft) pclog("Pushlc PC %08X\n", pc);
182.1821 +                                        PUSHL(pc); if (abrt) return;
182.1822 +                                }
182.1823 +                                else
182.1824 +                                {
182.1825 +                                        PUSHW(flags);
182.1826 +//                                        if (soft) pclog("Pushwc CS %04X\n", CS);
182.1827 +                                        PUSHW(CS);
182.1828 +//                                        if (soft) pclog("Pushwc PC %04X\n", pc);
182.1829 +                                        PUSHW(pc); if (abrt) return;
182.1830 +                                }
182.1831 +                                break;
182.1832 +                                default:
182.1833 +                                pclog("Int gate CS not code segment - %04X %04X %04X %04X\n",segdat2[0],segdat2[1],segdat2[2],segdat2[3]);
182.1834 +                                x86gpf(NULL,seg&~3);
182.1835 +                                return;
182.1836 +                        }
182.1837 +                CS=(seg&~3)|CPL;
182.1838 +//                pclog("New CS = %04X\n",CS);
182.1839 +                _cs.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
182.1840 +                if (segdat2[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.1841 +                _cs.base=segdat2[1];
182.1842 +                _cs.base|=((segdat2[2]&0xFF)<<16);
182.1843 +                if (is386) _cs.base|=((segdat2[3]>>8)<<24);
182.1844 +                _cs.access=segdat2[2]>>8;
182.1845 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.1846 +                if (type>0x800) pc=segdat[0]|(segdat[3]<<16);
182.1847 +                else            pc=segdat[0];
182.1848 +                use32=(segdat2[3]&0x40)?0x300:0;
182.1849 +//                pclog("Int gate done!\n");
182.1850 +
182.1851 +#ifdef CS_ACCESSED
182.1852 +                cpl_override = 1;
182.1853 +                writememw(0, oaddr+4, segdat2[2] | 0x100); /*Set accessed bit*/
182.1854 +                cpl_override = 0;
182.1855 +#endif
182.1856 +                        
182.1857 +                eflags&=~VM_FLAG;
182.1858 +                if (!(type&0x100))
182.1859 +                {
182.1860 +                        flags&=~I_FLAG;
182.1861 +//                        pclog("INT %02X disabling interrupts %i\n",num,soft);
182.1862 +                }
182.1863 +                flags&=~(T_FLAG|NT_FLAG);
182.1864 +//                if (output) pclog("Final Stack %04X:%08X\n",SS,ESP);
182.1865 +                break;
182.1866 +                
182.1867 +                case 0x500: /*Task gate*/
182.1868 +//                pclog("Task gate\n");
182.1869 +                seg=segdat[1];
182.1870 +                        addr=seg&~7;
182.1871 +                        if (seg&4)
182.1872 +                        {
182.1873 +                                if (addr>=ldt.limit)
182.1874 +                                {
182.1875 +                                        pclog("Bigger than LDT limit %04X %04X INT\n",seg,gdt.limit);
182.1876 +                                        x86gpf(NULL,seg&~3);
182.1877 +                                        return;
182.1878 +                                }
182.1879 +                                addr+=ldt.base;
182.1880 +                        }
182.1881 +                        else
182.1882 +                        {
182.1883 +                                if (addr>=gdt.limit)
182.1884 +                                {
182.1885 +                                        pclog("Bigger than GDT limit %04X %04X INT %i\n",seg,gdt.limit,ins);
182.1886 +                                        x86gpf(NULL,seg&~3);
182.1887 +                                        return;
182.1888 +                                }
182.1889 +                                addr+=gdt.base;
182.1890 +                        }
182.1891 +                        cpl_override=1;
182.1892 +                        segdat2[0]=readmemw(0,addr);
182.1893 +                        segdat2[1]=readmemw(0,addr+2);
182.1894 +                        segdat2[2]=readmemw(0,addr+4);
182.1895 +                        segdat2[3]=readmemw(0,addr+6);
182.1896 +                        cpl_override=0; if (abrt) return;
182.1897 +                                if (!(segdat2[2]&0x8000))
182.1898 +                                {
182.1899 +                                        pclog("Int task gate not present\n");
182.1900 +                                        x86np("Int task gate not present\n", segdat[1] & 0xfffc);
182.1901 +                                        return;
182.1902 +                                }
182.1903 +                optype=INT;
182.1904 +                cpl_override=1;
182.1905 +                taskswitch286(seg,segdat2,segdat2[2]&0x800);
182.1906 +                cpl_override=0;
182.1907 +                break;
182.1908 +                
182.1909 +                default:
182.1910 +                pclog("Bad int gate type %04X   %04X %04X %04X %04X\n",segdat[2]&0x1F00,segdat[0],segdat[1],segdat[2],segdat[3]);
182.1911 +                x86gpf(NULL,seg&~3);
182.1912 +                return;
182.1913 +        }
182.1914 +}
182.1915 +
182.1916 +int inint;
182.1917 +void pmodeiret(int is32)
182.1918 +{
182.1919 +        uint32_t newsp;
182.1920 +        uint16_t oldcs=CPL,newss;
182.1921 +        uint16_t tempw,tempw2;
182.1922 +        uint32_t tempflags,flagmask;
182.1923 +        uint32_t newpc;
182.1924 +        uint16_t segdat[4],segdat2[4];
182.1925 +        uint16_t segs[4];
182.1926 +        uint16_t seg;
182.1927 +        uint32_t addr, oaddr;
182.1928 +        uint32_t oldsp=ESP;
182.1929 +        if (is386 && (eflags&VM_FLAG))
182.1930 +        {
182.1931 +//                if (output) pclog("V86 IRET\n");
182.1932 +                if (IOPL!=3)
182.1933 +                {
182.1934 +                        pclog("V86 IRET! IOPL!=3\n");
182.1935 +                        x86gpf(NULL,0);
182.1936 +                        return;
182.1937 +                }
182.1938 +                oxpc=pc;
182.1939 +                if (is32)
182.1940 +                {
182.1941 +                        newpc=POPL();
182.1942 +                        seg=POPL();
182.1943 +                        tempflags=POPL(); if (abrt) return;
182.1944 +                }
182.1945 +                else
182.1946 +                {
182.1947 +                        newpc=POPW();
182.1948 +                        seg=POPW();
182.1949 +                        tempflags=POPW(); if (abrt) return;
182.1950 +                }
182.1951 +                pc=newpc;
182.1952 +                _cs.base=seg<<4;
182.1953 +                _cs.limit=0xFFFF;
182.1954 +                CS=seg;
182.1955 +                flags=(flags&0x3000)|(tempflags&0xCFD5)|2;
182.1956 +                return;
182.1957 +        }
182.1958 +
182.1959 +//        pclog("IRET %i\n",is32);
182.1960 +        //flushmmucache();
182.1961 +//        if (output) pclog("Pmode IRET %04X:%04X ",CS,pc);
182.1962 +
182.1963 +        if (flags&NT_FLAG)
182.1964 +        {
182.1965 +//                pclog("NT IRET\n");
182.1966 +                seg=readmemw(tr.base,0);
182.1967 +                addr=seg&~7;
182.1968 +                if (seg&4)
182.1969 +                {
182.1970 +                        if (addr>=ldt.limit)
182.1971 +                        {
182.1972 +                                pclog("TS Bigger than LDT limit %04X %04X IRET\n",seg,gdt.limit);
182.1973 +                                x86gpf(NULL,seg&~3);
182.1974 +                                return;
182.1975 +                        }
182.1976 +                        addr+=ldt.base;
182.1977 +                }
182.1978 +                else
182.1979 +                {
182.1980 +                        if (addr>=gdt.limit)
182.1981 +                        {
182.1982 +                                pclog("TS Bigger than GDT limit %04X %04X IRET\n",seg,gdt.limit);
182.1983 +                                x86gpf(NULL,seg&~3);
182.1984 +                                return;
182.1985 +                        }
182.1986 +                        addr+=gdt.base;
182.1987 +                }
182.1988 +                cpl_override=1;
182.1989 +                segdat[0]=readmemw(0,addr);
182.1990 +                segdat[1]=readmemw(0,addr+2);
182.1991 +                segdat[2]=readmemw(0,addr+4);
182.1992 +                segdat[3]=readmemw(0,addr+6);
182.1993 +                taskswitch286(seg,segdat,0);
182.1994 +                cpl_override=0;
182.1995 +                return;
182.1996 +        }
182.1997 +        inint=0;
182.1998 +        oxpc=pc;
182.1999 +        flagmask=0xFFFF;
182.2000 +        if (CPL) flagmask&=~0x3000;
182.2001 +        if (IOPL<CPL) flagmask&=~0x200;
182.2002 +//        if (output) pclog("IRET %i %i %04X %i\n",CPL,IOPL,flagmask,is32);
182.2003 +        if (is32)
182.2004 +        {
182.2005 +//                pclog("POP\n");
182.2006 +                newpc=POPL();
182.2007 +                seg=POPL();
182.2008 +                tempflags=POPL(); if (abrt) return;
182.2009 +//                if (output) pclog("IRETD pop %08X %08X %08X\n",newpc,seg,tempflags);
182.2010 +                if (is386 && ((tempflags>>16)&VM_FLAG))
182.2011 +                {
182.2012 +//                        pclog("IRETD to V86\n");
182.2013 +
182.2014 +                        newsp=POPL();
182.2015 +                        newss=POPL();
182.2016 +                        segs[0]=POPL();
182.2017 +                        segs[1]=POPL();
182.2018 +                        segs[2]=POPL();
182.2019 +                        segs[3]=POPL(); if (abrt) return;
182.2020 +//                        pclog("Pop stack %04X:%04X\n",newss,newsp);
182.2021 +                        eflags=tempflags>>16;
182.2022 +                        loadseg(segs[0],&_es);
182.2023 +                        loadseg(segs[1],&_ds);
182.2024 +                        loadseg(segs[2],&_fs);
182.2025 +                        loadseg(segs[3],&_gs);
182.2026 +                        
182.2027 +//                        pclog("V86 IRET %04X:%08X\n",SS,ESP);
182.2028 +//                        output=3;
182.2029 +                        
182.2030 +                        pc=newpc;
182.2031 +                        _cs.base=seg<<4;
182.2032 +                        _cs.limit=0xFFFF;
182.2033 +                        CS=seg;
182.2034 +                        _cs.access=3<<5;
182.2035 +                        if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.2036 +
182.2037 +                        ESP=newsp;
182.2038 +                        loadseg(newss,&_ss);
182.2039 +                        use32=0;
182.2040 +                        flags=(tempflags&0xFFD5)|2;
182.2041 +
182.2042 +//                        pclog("V86 IRET to %04X:%04X  %04X:%04X  %04X %04X %04X %04X %i\n",CS,pc,SS,SP,DS,ES,FS,GS,abrt);
182.2043 +  //                      if (CS==0xFFFF && pc==0xFFFFFFFF) timetolive=12;
182.2044 +/*                        {
182.2045 +                                dumpregs();
182.2046 +                                exit(-1);
182.2047 +                        }*/
182.2048 +                        return;
182.2049 +                }
182.2050 +        }
182.2051 +        else
182.2052 +        {
182.2053 +                newpc=POPW();
182.2054 +                seg=POPW();
182.2055 +                tempflags=POPW(); if (abrt) return;
182.2056 +        }
182.2057 +//        if (!is386) tempflags&=0xFFF;
182.2058 +//        pclog("Returned to %04X:%08X %04X %04X %i\n",seg,newpc,flags,tempflags, ins);
182.2059 +        if (!(seg&~3))
182.2060 +        {
182.2061 +                pclog("IRET CS=0\n");
182.2062 +//                dumpregs();
182.2063 +//                exit(-1);
182.2064 +                x86gpf(NULL,0);
182.2065 +                return;
182.2066 +        }
182.2067 +
182.2068 +//        if (output) pclog("IRET %04X:%08X\n",seg,newpc);
182.2069 +        addr=seg&~7;
182.2070 +        if (seg&4)
182.2071 +        {
182.2072 +                if (addr>=ldt.limit)
182.2073 +                {
182.2074 +                        pclog("Bigger than LDT limit %04X %04X IRET\n",seg,gdt.limit);
182.2075 +                        x86gpf(NULL,seg&~3);
182.2076 +                        return;
182.2077 +                }
182.2078 +                addr+=ldt.base;
182.2079 +        }
182.2080 +        else
182.2081 +        {
182.2082 +                if (addr>=gdt.limit)
182.2083 +                {
182.2084 +                        pclog("Bigger than GDT limit %04X %04X IRET\n",seg,gdt.limit);
182.2085 +                        x86gpf(NULL,seg&~3);
182.2086 +                        return;
182.2087 +                }
182.2088 +                addr+=gdt.base;
182.2089 +        }
182.2090 +        if ((seg&3) < CPL)
182.2091 +        {
182.2092 +                pclog("IRET to lower level\n");
182.2093 +                x86gpf(NULL,seg&~3);
182.2094 +                return;
182.2095 +        }
182.2096 +        cpl_override=1;
182.2097 +        segdat[0]=readmemw(0,addr);
182.2098 +        segdat[1]=readmemw(0,addr+2);
182.2099 +        segdat[2]=readmemw(0,addr+4);
182.2100 +        segdat[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) { ESP=oldsp; return; }
182.2101 +//        pclog("Seg type %04X %04X\n",segdat[2]&0x1F00,segdat[2]);
182.2102 +        
182.2103 +        switch (segdat[2]&0x1F00)
182.2104 +        {
182.2105 +                case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming code*/
182.2106 +                if ((seg&3) != DPL)
182.2107 +                {
182.2108 +                        pclog("IRET NC DPL  %04X   %04X %04X %04X %04X\n", seg, segdat[0], segdat[1], segdat[2], segdat[3]);
182.2109 +//                        dumpregs();
182.2110 +//                        exit(-1);
182.2111 +                        x86gpf(NULL,seg&~3);
182.2112 +                        return;
182.2113 +                }
182.2114 +                break;
182.2115 +                case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming code*/
182.2116 +                if ((seg&3) < DPL)
182.2117 +                {
182.2118 +                        pclog("IRET C DPL\n");
182.2119 +                        x86gpf(NULL,seg&~3);
182.2120 +                        return;
182.2121 +                }
182.2122 +                break;
182.2123 +                default:
182.2124 +                pclog("IRET CS != code seg\n");
182.2125 +                x86gpf(NULL,seg&~3);
182.2126 +//                dumpregs();
182.2127 +//                exit(-1);
182.2128 +                return;
182.2129 +        }
182.2130 +        if (!(segdat[2]&0x8000))
182.2131 +        {
182.2132 +                pclog("IRET CS not present %i  %04X %04X %04X\n",ins, segdat[0], segdat[1], segdat[2]);
182.2133 +                ESP=oldsp;
182.2134 +                x86np("IRET CS not present\n", seg & 0xfffc);
182.2135 +                return;
182.2136 +        }
182.2137 +//        pclog("Seg %04X CPL %04X\n",seg,CPL);
182.2138 +        if ((seg&3) == CPL)
182.2139 +        {
182.2140 +//                pclog("Same level\n");
182.2141 +                CS=seg;
182.2142 +                _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.2143 +                if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.2144 +                _cs.base=segdat[1];
182.2145 +                _cs.base|=((segdat[2]&0xFF)<<16);
182.2146 +                if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.2147 +                _cs.access=segdat[2]>>8;
182.2148 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.2149 +                use32=(segdat[3]&0x40)?0x300:0;
182.2150 +
182.2151 +#ifdef CS_ACCESSED                
182.2152 +                cpl_override = 1;
182.2153 +                writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.2154 +                cpl_override = 0;
182.2155 +#endif
182.2156 +        }
182.2157 +        else /*Return to outer level*/
182.2158 +        {
182.2159 +                oaddr = addr;
182.2160 +                if (output) pclog("Outer level\n");
182.2161 +                if (is32)
182.2162 +                {
182.2163 +                        newsp=POPL();
182.2164 +                        newss=POPL(); if (abrt) return;
182.2165 +                }
182.2166 +                else
182.2167 +                {
182.2168 +                        newsp=POPW();
182.2169 +                        newss=POPW(); if (abrt) return;
182.2170 +                }
182.2171 +                
182.2172 +                if (output) pclog("IRET load stack %04X:%04X\n",newss,newsp);
182.2173 +                
182.2174 +                if (!(newss&~3))
182.2175 +                {
182.2176 +                        pclog("IRET loading null SS\n");
182.2177 +                        x86gpf(NULL,newss&~3);
182.2178 +                        return;
182.2179 +                }
182.2180 +                addr=newss&~7;
182.2181 +                if (newss&4)
182.2182 +                {
182.2183 +                        if (addr>=ldt.limit)
182.2184 +                        {
182.2185 +                                pclog("Bigger than LDT limit %04X %04X PMODEIRET SS\n",newss,gdt.limit);
182.2186 +                                x86gpf(NULL,newss&~3);
182.2187 +                                return;
182.2188 +                        }
182.2189 +                        addr+=ldt.base;
182.2190 +                }
182.2191 +                else
182.2192 +                {
182.2193 +                        if (addr>=gdt.limit)
182.2194 +                        {
182.2195 +                                pclog("Bigger than GDT limit %04X %04X PMODEIRET\n",newss,gdt.limit);
182.2196 +                                x86gpf(NULL,newss&~3);
182.2197 +                                return;
182.2198 +                        }
182.2199 +                        addr+=gdt.base;
182.2200 +                }
182.2201 +                cpl_override=1;
182.2202 +                segdat2[0]=readmemw(0,addr);
182.2203 +                segdat2[1]=readmemw(0,addr+2);
182.2204 +                segdat2[2]=readmemw(0,addr+4);
182.2205 +                segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (abrt) { ESP=oldsp; return; }
182.2206 +//                pclog("IRET SS sd2 %04X\n",segdat2[2]);
182.2207 +//                if (((newss & 3) != DPL) || (DPL2 != DPL))
182.2208 +                if ((newss & 3) != (seg & 3))
182.2209 +                {
182.2210 +                        pclog("IRET loading SS with wrong permissions  %04X %04X\n", newss, seg);
182.2211 +//                        dumpregs();
182.2212 +//                        exit(-1);
182.2213 +                        x86gpf(NULL,newss&~3);
182.2214 +                        return;
182.2215 +                }
182.2216 +                if ((segdat2[2]&0x1A00)!=0x1200)
182.2217 +                {
182.2218 +                        pclog("IRET loading SS wrong type\n");
182.2219 +                        x86gpf(NULL,newss&~3);
182.2220 +                        return;
182.2221 +                }
182.2222 +                if (DPL2 != (seg & 3))
182.2223 +                {
182.2224 +                        pclog("IRET loading SS with wrong permissions2 %i %i  %04X %04X\n", DPL2, seg & 3, newss, seg);
182.2225 +                        ESP=oldsp;
182.2226 +                        x86gpf(NULL,newss&~3);
182.2227 +                        return;
182.2228 +                }
182.2229 +                if (!(segdat2[2]&0x8000))
182.2230 +                {
182.2231 +                        pclog("IRET loading SS not present\n");
182.2232 +                        x86np("IRET loading SS not present\n", newss & 0xfffc);
182.2233 +                        return;
182.2234 +                }
182.2235 +                SS=newss;
182.2236 +                stack32=segdat2[3]&0x40;
182.2237 +                if (stack32) ESP=newsp;
182.2238 +                else         SP=newsp;
182.2239 +                _ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
182.2240 +                if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
182.2241 +                if ((segdat2[2]>>8) & 4)
182.2242 +                   _ss.limit = 0xffffffff;
182.2243 +                _ss.limitw=(segdat2[2]&0x200)?1:0;
182.2244 +                _ss.base=segdat2[1];
182.2245 +                _ss.base|=((segdat2[2]&0xFF)<<16);
182.2246 +                if (is386) _ss.base|=((segdat2[3]>>8)<<24);
182.2247 +                _ss.access=segdat2[2]>>8;
182.2248 +
182.2249 +#ifdef SEL_ACCESSED
182.2250 +                cpl_override = 1;
182.2251 +                writememw(0, addr+4, segdat2[2] | 0x100); /*Set accessed bit*/
182.2252 +
182.2253 +#ifdef CS_ACCESSED
182.2254 +                writememw(0, oaddr+4, segdat[2] | 0x100); /*Set accessed bit*/
182.2255 +#endif
182.2256 +                cpl_override = 0;
182.2257 +#endif                
182.2258 +                        /*Conforming segments don't change CPL, so CPL = RPL*/
182.2259 +                        if (segdat[2]&0x400)
182.2260 +                           segdat[2] = (segdat[2] & ~(3 << 5+8)) | ((seg & 3) << 5+8);
182.2261 +
182.2262 +                CS=seg;
182.2263 +                _cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
182.2264 +                if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.2265 +                _cs.base=segdat[1];
182.2266 +                _cs.base|=((segdat[2]&0xFF)<<16);
182.2267 +                if (is386) _cs.base|=((segdat[3]>>8)<<24);
182.2268 +                _cs.access=segdat[2]>>8;
182.2269 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.2270 +                use32=(segdat[3]&0x40)?0x300:0;
182.2271 +                        
182.2272 +                if (CPL>((_ds.access>>5)&3))
182.2273 +                {
182.2274 +                        _ds.seg=0;
182.2275 +                        _ds.base=-1;
182.2276 +                }
182.2277 +                if (CPL>((_es.access>>5)&3))
182.2278 +                {
182.2279 +                        _es.seg=0;
182.2280 +                        _es.base=-1;
182.2281 +                }
182.2282 +                if (CPL>((_fs.access>>5)&3))
182.2283 +                {
182.2284 +                        _fs.seg=0;
182.2285 +                        _fs.base=-1;
182.2286 +                }
182.2287 +                if (CPL>((_gs.access>>5)&3))
182.2288 +                {
182.2289 +                        _gs.seg=0;
182.2290 +                        _gs.base=-1;
182.2291 +                }
182.2292 +        }
182.2293 +        pc=newpc;
182.2294 +        flags=(flags&~flagmask)|(tempflags&flagmask&0xFFD5)|2;
182.2295 +        if (is32) eflags=tempflags>>16;
182.2296 +//        pclog("done\n");
182.2297 +}
182.2298 +
182.2299 +void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
182.2300 +{
182.2301 +        uint32_t base,obase=tr.base;
182.2302 +        uint32_t limit;
182.2303 +        int x386;
182.2304 +        uint32_t templ;
182.2305 +        uint16_t tempw;
182.2306 +        int c;
182.2307 +
182.2308 +	uint32_t new_cr3=0;
182.2309 +	uint16_t new_es,new_cs,new_ss,new_ds,new_fs,new_gs;
182.2310 +	uint16_t new_ldt;
182.2311 +
182.2312 +	uint32_t new_eax,new_ebx,new_ecx,new_edx,new_esp,new_ebp,new_esi,new_edi,new_pc,new_flags;
182.2313 +
182.2314 +        uint32_t addr;
182.2315 +        
182.2316 +	uint16_t oldflags;
182.2317 +	
182.2318 +	uint16_t segdat2[4];
182.2319 +
182.2320 +//output=3;
182.2321 +        base=segdat[1]|((segdat[2]&0xFF)<<16)|((segdat[3]>>8)<<24);
182.2322 +        limit=segdat[0]|((segdat[3]&0xF)<<16);
182.2323 +//        pclog("286 Task switch! %04X:%04X\n",CS,pc);
182.2324 +///        pclog("TSS %04X base %08X limit %04X old TSS %04X %08X %i\n",seg,base,limit,tr.seg,tr.base,ins);
182.2325 +// /       pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]);
182.2326 +
182.2327 +        if (is386)
182.2328 +        {
182.2329 +//                if (output) pclog("32-bit TSS\n");
182.2330 +                
182.2331 +                new_cr3=readmeml(base,0x1C);
182.2332 +                new_pc=readmeml(base,0x20);
182.2333 +                new_flags=readmeml(base,0x24);
182.2334 +                
182.2335 +                new_eax=readmeml(base,0x28);
182.2336 +                new_ecx=readmeml(base,0x2C);
182.2337 +                new_edx=readmeml(base,0x30);
182.2338 +                new_ebx=readmeml(base,0x34);
182.2339 +                new_esp=readmeml(base,0x38);
182.2340 +                new_ebp=readmeml(base,0x3C);
182.2341 +                new_esi=readmeml(base,0x40);
182.2342 +                new_edi=readmeml(base,0x44);
182.2343 +
182.2344 +                new_es=readmemw(base,0x48);
182.2345 +//                if (output) pclog("Read CS from %08X\n",base+0x4C);
182.2346 +                new_cs=readmemw(base,0x4C);
182.2347 +                new_ss=readmemw(base,0x50);
182.2348 +                new_ds=readmemw(base,0x54);
182.2349 +                new_fs=readmemw(base,0x58);
182.2350 +                new_gs=readmemw(base,0x5C);
182.2351 +                new_ldt=readmemw(base,0x60);
182.2352 +                
182.2353 +                if (abrt) return;
182.2354 +                if (optype==JMP || optype==INT)
182.2355 +                {
182.2356 +                        if (tr.seg&4) tempw=readmemw(ldt.base,(tr.seg&~7)+4);
182.2357 +                        else          tempw=readmemw(gdt.base,(tr.seg&~7)+4);
182.2358 +                        if (abrt) return;
182.2359 +                        tempw&=~0x200;
182.2360 +                        if (tr.seg&4) writememw(ldt.base,(tr.seg&~7)+4,tempw);
182.2361 +                        else          writememw(gdt.base,(tr.seg&~7)+4,tempw);
182.2362 +                }
182.2363 +                
182.2364 +                if (optype==IRET) flags&=~NT_FLAG;
182.2365 +                
182.2366 +//                if (output) pclog("Write PC %08X %08X\n",tr.base,pc);
182.2367 +                writememl(tr.base,0x1C,cr3);
182.2368 +                writememl(tr.base,0x20,pc);
182.2369 +                writememl(tr.base,0x24,flags|(eflags<<16));
182.2370 +                
182.2371 +                writememl(tr.base,0x28,EAX);
182.2372 +                writememl(tr.base,0x2C,ECX);
182.2373 +                writememl(tr.base,0x30,EDX);
182.2374 +                writememl(tr.base,0x34,EBX);
182.2375 +                writememl(tr.base,0x38,ESP);
182.2376 +                writememl(tr.base,0x3C,EBP);
182.2377 +                writememl(tr.base,0x40,ESI);
182.2378 +                writememl(tr.base,0x44,EDI);
182.2379 +                
182.2380 +                writememl(tr.base,0x48,ES);
182.2381 +//                if (output) pclog("Write CS %04X to %08X\n",CS,tr.base+0x4C);
182.2382 +                writememl(tr.base,0x4C,CS);
182.2383 +                writememl(tr.base,0x50,SS);
182.2384 +                writememl(tr.base,0x54,DS);
182.2385 +                writememl(tr.base,0x58,FS);
182.2386 +                writememl(tr.base,0x5C,GS);
182.2387 +                writememl(tr.base,0x60,ldt.seg);
182.2388 +                
182.2389 +                if (optype==INT)
182.2390 +                {
182.2391 +                        writememl(base,0,tr.seg);
182.2392 +                        new_flags|=NT_FLAG;
182.2393 +                }
182.2394 +                if (abrt) return;
182.2395 +                if (optype==JMP || optype==INT)
182.2396 +                {
182.2397 +                        if (tr.seg&4) tempw=readmemw(ldt.base,(seg&~7)+4);
182.2398 +                        else          tempw=readmemw(gdt.base,(seg&~7)+4);
182.2399 +                        if (abrt) return;
182.2400 +                        tempw|=0x200;
182.2401 +                        if (tr.seg&4) writememw(ldt.base,(seg&~7)+4,tempw);
182.2402 +                        else          writememw(gdt.base,(seg&~7)+4,tempw);
182.2403 +                }
182.2404 +                
182.2405 +                
182.2406 +                
182.2407 +                cr3=new_cr3;
182.2408 +//                pclog("New CR3 %08X\n",cr3);
182.2409 +                flushmmucache();
182.2410 +                
182.2411 +                
182.2412 +                
182.2413 +                pc=new_pc;
182.2414 +//                if (output) pclog("New pc %08X\n",new_pc);
182.2415 +                flags=new_flags;
182.2416 +                eflags=new_flags>>16;
182.2417 +
182.2418 +//                if (output) pclog("Load LDT %04X\n",new_ldt);
182.2419 +                ldt.seg=new_ldt;
182.2420 +                templ=(ldt.seg&~7)+gdt.base;
182.2421 +//                if (output) pclog("Load from %08X %08X\n",templ,gdt.base);
182.2422 +                ldt.limit=readmemw(0,templ);
182.2423 +                if (readmemb(templ+6)&0x80)
182.2424 +                {
182.2425 +                        ldt.limit<<=12;
182.2426 +                        ldt.limit|=0xFFF;
182.2427 +                }
182.2428 +                ldt.base=(readmemw(0,templ+2))|(readmemb(templ+4)<<16)|(readmemb(templ+7)<<24);
182.2429 +//                if (output) pclog("Limit %04X Base %08X\n",ldt.limit,ldt.base);
182.2430 +
182.2431 +
182.2432 +                if (eflags&VM_FLAG)
182.2433 +                {
182.2434 +                        pclog("Task switch V86!\n");
182.2435 +                        x86gpf(NULL,0);
182.2436 +                        return;
182.2437 +                }
182.2438 +
182.2439 +                if (!(new_cs&~3))
182.2440 +                {
182.2441 +                        pclog("TS loading null CS\n");
182.2442 +                        x86gpf(NULL,0);
182.2443 +                        return;
182.2444 +                }
182.2445 +                addr=new_cs&~7;
182.2446 +                if (new_cs&4)
182.2447 +                {
182.2448 +                        if (addr>=ldt.limit)
182.2449 +                        {
182.2450 +                                pclog("Bigger than LDT limit %04X %04X %04X TS\n",new_cs,ldt.limit,addr);
182.2451 +                                x86gpf(NULL,0);
182.2452 +                                return;
182.2453 +                        }
182.2454 +                        addr+=ldt.base;
182.2455 +                }
182.2456 +                else
182.2457 +                {
182.2458 +                        if (addr>=gdt.limit)
182.2459 +                        {
182.2460 +                                pclog("Bigger than GDT limit %04X %04X TS\n",new_cs,gdt.limit);
182.2461 +                                x86gpf(NULL,0);
182.2462 +                                return;
182.2463 +                        }
182.2464 +                        addr+=gdt.base;
182.2465 +                }
182.2466 +                segdat2[0]=readmemw(0,addr);
182.2467 +                segdat2[1]=readmemw(0,addr+2);
182.2468 +                segdat2[2]=readmemw(0,addr+4);
182.2469 +                segdat2[3]=readmemw(0,addr+6);
182.2470 +                if (!(segdat2[2]&0x8000))
182.2471 +                {
182.2472 +                        pclog("TS loading CS not present\n");
182.2473 +                        x86np("TS loading CS not present\n", new_cs & 0xfffc);
182.2474 +                        return;
182.2475 +                }
182.2476 +                switch (segdat2[2]&0x1F00)
182.2477 +                {
182.2478 +                        case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming*/
182.2479 +                        if ((new_cs&3) != DPL2)
182.2480 +                        {
182.2481 +                                pclog("TS load CS non-conforming RPL != DPL");
182.2482 +                                x86gpf(NULL,new_cs&~3);
182.2483 +                                return;
182.2484 +                        }
182.2485 +                        break;
182.2486 +                        case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
182.2487 +                        if ((new_cs&3) < DPL2)
182.2488 +                        {
182.2489 +                                pclog("TS load CS non-conforming RPL < DPL");
182.2490 +                                x86gpf(NULL,new_cs&~3);
182.2491 +                                return;
182.2492 +                        }
182.2493 +                        break;
182.2494 +                        default:
182.2495 +                        pclog("TS load CS not code segment\n");
182.2496 +                        x86gpf(NULL,new_cs&~3);
182.2497 +                        return;
182.2498 +                }
182.2499 +
182.2500 +//                if (output) pclog("new_cs %04X\n",new_cs);
182.2501 +                CS=new_cs;
182.2502 +                _cs.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
182.2503 +                if (segdat2[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
182.2504 +                _cs.base=segdat2[1];
182.2505 +                _cs.base|=((segdat2[2]&0xFF)<<16);
182.2506 +                if (is386) _cs.base|=((segdat2[3]>>8)<<24);
182.2507 +                _cs.access=segdat2[2]>>8;
182.2508 +                if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
182.2509 +                use32=(segdat2[3]&0x40)?0x300:0;
182.2510 +
182.2511 +                EAX=new_eax;
182.2512 +                ECX=new_ecx;
182.2513 +                EDX=new_edx;
182.2514 +                EBX=new_ebx;
182.2515 +                ESP=new_esp;
182.2516 +                EBP=new_ebp;
182.2517 +                ESI=new_esi;
182.2518 +                EDI=new_edi;
182.2519 +
182.2520 +                if (output) pclog("Load ES %04X\n",new_es);
182.2521 +                loadseg(new_es,&_es);
182.2522 +                if (output) pclog("Load SS %04X\n",new_ss);
182.2523 +                loadseg(new_ss,&_ss);
182.2524 +                if (output) pclog("Load DS %04X\n",new_ds);
182.2525 +                loadseg(new_ds,&_ds);
182.2526 +                if (output) pclog("Load FS %04X\n",new_fs);
182.2527 +                loadseg(new_fs,&_fs);
182.2528 +                if (output) pclog("Load GS %04X\n",new_gs);
182.2529 +                loadseg(new_gs,&_gs);
182.2530 +
182.2531 +                if (output) pclog("Resuming at %04X:%08X\n",CS,pc);
182.2532 +        }
182.2533 +        else
182.2534 +        {
182.2535 +                pclog("16-bit TSS\n");
182.2536 +                resetx86();
182.2537 +                //exit(-1);
182.2538 +        }
182.2539 +
182.2540 +
182.2541 +        tr.seg=seg;
182.2542 +        tr.base=base;
182.2543 +        tr.limit=limit;
182.2544 +        tr.access=segdat[2]>>8;
182.2545 +}
182.2546 +
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/src/x87.c	Sun Apr 21 14:54:35 2013 +0100
   183.3 @@ -0,0 +1,1106 @@
   183.4 +//Quake timedemo demo1 - 8.1FPS
   183.5 +
   183.6 +//11A00 - D_SCAlloc
   183.7 +//11C1C - D_CacheSurface
   183.8 +
   183.9 +//36174 - SCR_CalcRefdef
  183.10 +
  183.11 +//SCR_CalcRefdef
  183.12 +//Calls R_SetVrect and R_ViewChanged
  183.13 +
  183.14 +#include <math.h>
  183.15 +#include "ibm.h"
  183.16 +#include "x86.h"
  183.17 +#include "x87.h"
  183.18 +
  183.19 +#undef readmemb
  183.20 +#undef writememb
  183.21 +
  183.22 +#define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)?readmemb386l(s,a):ram[readlookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)])
  183.23 +#define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememb386l(s,a,v); else ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]=v
  183.24 +
  183.25 +#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
  183.26 +#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
  183.27 +
  183.28 +static inline uint8_t geteab()
  183.29 +{
  183.30 +        if (mod==3)
  183.31 +           return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
  183.32 +//        cycles-=3;
  183.33 +        if (eal_r) return *(uint8_t *)eal_r;
  183.34 +        return readmemb(easeg,eaaddr);
  183.35 +}
  183.36 +
  183.37 +static inline uint16_t geteaw()
  183.38 +{
  183.39 +        if (mod==3)
  183.40 +           return regs[rm].w;
  183.41 +//        cycles-=3;
  183.42 +        if (eal_r) return *(uint16_t *)eal_r;
  183.43 +        return readmemw(easeg,eaaddr);
  183.44 +}
  183.45 +
  183.46 +static inline uint32_t geteal()
  183.47 +{
  183.48 +        if (mod==3)
  183.49 +           return regs[rm].l;
  183.50 +//        cycles-=3;
  183.51 +        if (eal_r) return *eal_r;
  183.52 +        return readmeml(easeg,eaaddr);
  183.53 +}
  183.54 +
  183.55 +
  183.56 +#define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v;  else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v
  183.57 +#define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v);    } else regs[rm].w=v
  183.58 +#define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v;             else writememll(easeg,eaaddr,v);    } else regs[rm].l=v
  183.59 +
  183.60 +
  183.61 +
  183.62 +double ST[8];
  183.63 +uint16_t npxs,npxc,tag;
  183.64 +
  183.65 +int TOP;
  183.66 +#define ST(x) ST[((TOP+(x))&7)]
  183.67 +
  183.68 +#define C0 (1<<8)
  183.69 +#define C1 (1<<9)
  183.70 +#define C2 (1<<10)
  183.71 +#define C3 (1<<14)
  183.72 +
  183.73 +void x87_reset()
  183.74 +{
  183.75 +}
  183.76 +
  183.77 +void x87_dumpregs()
  183.78 +{
  183.79 +        pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
  183.80 +        pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]);
  183.81 +        pclog("Status = %04X  Control = %04X  Tag = %04X\n",npxs,npxc,tag);
  183.82 +}
  183.83 +
  183.84 +void x87_print()
  183.85 +{
  183.86 +        pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",ST[TOP],ST[(TOP+1)&7],ST[(TOP+2)&7],ST[(TOP+3)&7]);
  183.87 +        pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n\n",ST[(TOP+4)&7],ST[(TOP+5)&7],ST[(TOP+6)&7],ST[(TOP+7)&7]);
  183.88 +}
  183.89 +
  183.90 +void x87_push(double i)
  183.91 +{
  183.92 +        TOP=(TOP-1)&7;
  183.93 +        ST[TOP]=i;
  183.94 +        tag&=~(3<<((TOP&7)<<1));
  183.95 +        if (i==0.0) tag|=(1<<((TOP&7)<<1));
  183.96 +}
  183.97 +
  183.98 +double x87_pop()
  183.99 +{
 183.100 +        double t=ST[TOP];
 183.101 +        tag|=(3<<((TOP&7)<<1));
 183.102 +        TOP=(TOP+1)&7;
 183.103 +        return t;
 183.104 +}
 183.105 +
 183.106 +int64_t x87_fround(double b)
 183.107 +{
 183.108 +        switch ((npxc>>10)&3)
 183.109 +        {
 183.110 +                case 0: /*Nearest*/
 183.111 +                return (int64_t)(b+0.5);
 183.112 +                case 1: /*Down*/
 183.113 +                return (int64_t)floor(b);
 183.114 +                case 2: /*Up*/
 183.115 +                return (int64_t)ceil(b);
 183.116 +                case 3: /*Chop*/
 183.117 +                return (int64_t)b;
 183.118 +        }
 183.119 +}
 183.120 +#define BIAS80 16383
 183.121 +#define BIAS64 1023
 183.122 +
 183.123 +double x87_ld80()
 183.124 +{
 183.125 +	struct {
 183.126 +		int16_t begin;
 183.127 +		union
 183.128 +		{
 183.129 +                        double d;
 183.130 +                        uint64_t ll;
 183.131 +                } eind;
 183.132 +	} test;
 183.133 +	test.eind.ll = readmeml(easeg,eaaddr);
 183.134 +	test.eind.ll |= (uint64_t)readmeml(easeg,eaaddr+4)<<32;
 183.135 +	test.begin = readmemw(easeg,eaaddr+8);
 183.136 +
 183.137 +	int64_t exp64 = (((test.begin&0x7fff) - BIAS80));
 183.138 +	int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff;
 183.139 +	int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64;
 183.140 +
 183.141 +	int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff);
 183.142 +	int64_t sign = (test.begin&0x8000)?1:0;
 183.143 +
 183.144 +        if (test.eind.ll&0x400) mant64++;
 183.145 +//        pclog("LD80 %08X %08X\n",test.eind.ll,mant64);
 183.146 +	test.eind.ll = (sign <<63)|(exp64final << 52)| mant64;
 183.147 +	return test.eind.d;
 183.148 +}
 183.149 +
 183.150 +void x87_st80(double d)
 183.151 +{
 183.152 +	struct {
 183.153 +		int16_t begin;
 183.154 +		union
 183.155 +		{
 183.156 +                        double d;
 183.157 +                        uint64_t ll;
 183.158 +                } eind;
 183.159 +	} test;
 183.160 +	test.eind.d=d;
 183.161 +	int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0;
 183.162 +	int64_t exp80 =  test.eind.ll&(0x7ff0000000000000);
 183.163 +	int64_t exp80final = (exp80>>52);
 183.164 +	int64_t mant80 = test.eind.ll&(0x000fffffffffffff);
 183.165 +	int64_t mant80final = (mant80 << 11);
 183.166 +	if(d != 0){ //Zero is a special case
 183.167 +		// Elvira wants the 8 and tcalc doesn't
 183.168 +		mant80final |= (0x8000000000000000);
 183.169 +		//Ca-cyber doesn't like this when result is zero.
 183.170 +		exp80final += (BIAS80 - BIAS64);
 183.171 +	}
 183.172 +	test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final;
 183.173 +	test.eind.ll = mant80final;
 183.174 +	writememl(easeg,eaaddr,test.eind.ll);
 183.175 +	writememl(easeg,eaaddr+4,test.eind.ll>>32);
 183.176 +	writememw(easeg,eaaddr+8,test.begin);
 183.177 +}
 183.178 +
 183.179 +void x87_d8()
 183.180 +{
 183.181 +        union
 183.182 +        {
 183.183 +                float s;
 183.184 +                uint32_t i;
 183.185 +        } ts;
 183.186 +        if (mod==3)
 183.187 +        {
 183.188 +                switch (rmdat32&0xFF)
 183.189 +                {
 183.190 +                        case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/
 183.191 +                        case 0xC4: case 0xC5: case 0xC6: case 0xC7:
 183.192 +                        ST(0)=ST(0)+ST(rmdat32&7);
 183.193 +                        cycles-=8;
 183.194 +                        return;
 183.195 +                        case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/
 183.196 +                        case 0xCC: case 0xCD: case 0xCE: case 0xCF:
 183.197 +                        ST(0)=ST(0)*ST(rmdat32&7);
 183.198 +                        cycles-=16;
 183.199 +                        return;
 183.200 +                        case 0xD0: case 0xD1: case 0xD2: case 0xD3: /*FCOM*/
 183.201 +                        case 0xD4: case 0xD5: case 0xD6: case 0xD7:
 183.202 +                        npxs&=~(C0|C2|C3);
 183.203 +                        if (ST(0)==ST(rmdat32&7))     npxs|=C3;
 183.204 +                        else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
 183.205 +                        cycles-=4;
 183.206 +                        return;
 183.207 +                        case 0xD8: case 0xD9: case 0xDA: case 0xDB: /*FCOMP*/
 183.208 +                        case 0xDC: case 0xDD: case 0xDE: case 0xDF:
 183.209 +                        npxs&=~(C0|C2|C3);
 183.210 +                        if (ST(0)==ST(rmdat32&7))     npxs|=C3;
 183.211 +                        else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
 183.212 +                        x87_pop();
 183.213 +                        cycles-=4;
 183.214 +                        return;
 183.215 +                        case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUB*/
 183.216 +                        case 0xE4: case 0xE5: case 0xE6: case 0xE7:
 183.217 +                        ST(0)=ST(0)-ST(rmdat32&7);
 183.218 +                        cycles-=8;
 183.219 +                        return;
 183.220 +                        case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBR*/
 183.221 +                        case 0xEC: case 0xED: case 0xEE: case 0xEF:
 183.222 +                        ST(0)=ST(rmdat32&7)-ST(0);
 183.223 +                        cycles-=8;
 183.224 +                        return;
 183.225 +                        case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIV*/
 183.226 +                        case 0xF4: case 0xF5: case 0xF6: case 0xF7:
 183.227 +                        ST(0)=ST(0)/ST(rmdat32&7);
 183.228 +                        cycles-=73;
 183.229 +                        return;
 183.230 +                        case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVR*/
 183.231 +                        case 0xFC: case 0xFD: case 0xFE: case 0xFF:
 183.232 +                        ST(0)=ST(rmdat32&7)/ST(0);
 183.233 +                        cycles-=73;
 183.234 +                        return;
 183.235 +                }
 183.236 +        }
 183.237 +        else
 183.238 +        {
 183.239 +                ts.i=geteal(); if (abrt) return;
 183.240 +                switch (reg)
 183.241 +                {
 183.242 +                        case 0: /*FADD short*/
 183.243 +                        ST(0)+=ts.s;
 183.244 +                        cycles-=8;
 183.245 +                        return;
 183.246 +                        case 1: /*FMUL short*/
 183.247 +                        ST(0)*=ts.s;
 183.248 +                        cycles-=11;
 183.249 +                        return;
 183.250 +                        case 2: /*FCOM short*/
 183.251 +                        npxs&=~(C0|C2|C3);
 183.252 +                        if (ST(0)==ts.s)     npxs|=C3;
 183.253 +                        else if (ST(0)<ts.s) npxs|=C0;
 183.254 +                        cycles-=4;
 183.255 +                        return;
 183.256 +                        case 3: /*FCOMP short*/
 183.257 +                        npxs&=~(C0|C2|C3);
 183.258 +                        if (ST(0)==ts.s)     npxs|=C3;
 183.259 +                        else if (ST(0)<ts.s) npxs|=C0;
 183.260 +                        cycles-=4;
 183.261 +                        x87_pop();
 183.262 +                        return;
 183.263 +                        case 4: /*FSUB short*/
 183.264 +                        ST(0)-=ts.s;
 183.265 +                        cycles-=8;
 183.266 +                        return;
 183.267 +                        case 5: /*FSUBR short*/
 183.268 +                        ST(0)=ts.s-ST(0);
 183.269 +                        cycles-=8;
 183.270 +                        return;
 183.271 +                        case 6: /*FDIV short*/
 183.272 +                        ST(0)=ST(0)/ts.s;
 183.273 +                        cycles-=73;
 183.274 +                        return;
 183.275 +                        case 7: /*FDIVR short*/
 183.276 +                        ST(0)=ts.s/ST(0);
 183.277 +                        cycles-=73;
 183.278 +                        return;
 183.279 +                }
 183.280 +        }
 183.281 +        x86illegal();
 183.282 +//        fatal("Bad x87 D8 opcode %i %02X\n",reg,rmdat32&0xFF);
 183.283 +}
 183.284 +void x87_d9()
 183.285 +{
 183.286 +        union
 183.287 +        {
 183.288 +                float s;
 183.289 +                uint32_t i;
 183.290 +        } ts;
 183.291 +        float t;
 183.292 +        double td;
 183.293 +        int64_t temp64;
 183.294 +        uint16_t tempw;
 183.295 +        if (mod==3)
 183.296 +        {
 183.297 +                switch (rmdat32&0xFF)
 183.298 +                {
 183.299 +                        case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FLD*/
 183.300 +                        case 0xC4: case 0xC5: case 0xC6: case 0xC7:
 183.301 +                        x87_push(ST(rmdat32&7));
 183.302 +                        cycles-=4;
 183.303 +                        return;
 183.304 +                        case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FXCH*/
 183.305 +                        case 0xCC: case 0xCD: case 0xCE: case 0xCF:
 183.306 +                        td=ST(0);
 183.307 +                        ST(0)=ST(rmdat32&7);
 183.308 +                        ST(rmdat32&7)=td;
 183.309 +                        cycles-=4;
 183.310 +                        return;
 183.311 +                        case 0xD0: /*FNOP*/
 183.312 +                        cycles-=3;
 183.313 +                        return;
 183.314 +                        case 0xE0: /*FCHS*/
 183.315 +                        ST(0)=-ST(0);
 183.316 +                        cycles-=6;
 183.317 +                        return;
 183.318 +                        case 0xE1: /*FABS*/
 183.319 +                        ST(0)=fabs(ST(0));
 183.320 +                        cycles-=3;
 183.321 +                        return;
 183.322 +                        case 0xE4: /*FTST*/
 183.323 +                        npxs&=~(C0|C2|C3);
 183.324 +                        if (ST(0)==0.0)     npxs|=C3;
 183.325 +                        else if (ST(0)<0.0) npxs|=C0;
 183.326 +                        cycles-=4;
 183.327 +                        return;
 183.328 +                        case 0xE5: /*FXAM*/
 183.329 +//                        pclog("FXAM %f %i\n",ST(0),(tag>>((TOP&1)<<1))&3);
 183.330 +                        npxs&=~(C0|C2|C3);
 183.331 +                        if (((tag>>((TOP&1)<<1))&3)==3) npxs|=(C0|C3);
 183.332 +                        else if (ST(0)==0.0)            npxs|=C3;
 183.333 +                        else                            npxs|=C2;
 183.334 +                        if (ST(0)<0.0)                  npxs|=C1;
 183.335 +                        cycles-=8;
 183.336 +                        return;
 183.337 +                        case 0xE8: /*FLD1*/
 183.338 +                        x87_push(1.0);
 183.339 +                        cycles-=4;
 183.340 +                        return;
 183.341 +                        case 0xE9: /*FLDL2T*/
 183.342 +                        x87_push(3.3219280948873623);
 183.343 +                        cycles-=8;
 183.344 +                        return;
 183.345 +                        case 0xEA: /*FLDL2E*/
 183.346 +                        x87_push(1.4426950408889634);
 183.347 +                        cycles-=8;
 183.348 +                        return;
 183.349 +                        case 0xEB: /*FLDPI*/
 183.350 +                        x87_push(3.141592653589793);
 183.351 +                        cycles-=8;
 183.352 +                        return;
 183.353 +                        case 0xEC: /*FLDEG2*/
 183.354 +                        x87_push(0.3010299956639812);
 183.355 +                        cycles-=8;
 183.356 +                        return;
 183.357 +                        case 0xED: /*FLDLN2*/
 183.358 +                        x87_push(0.693147180559945);
 183.359 +                        cycles-=8;
 183.360 +                        return;
 183.361 +                        case 0xEE: /*FLDZ*/
 183.362 +//                        pclog("FLDZ %04X:%08X\n",CS,pc);
 183.363 +                        x87_push(0.0);
 183.364 +                        tag|=(1<<((TOP&7)<<1));
 183.365 +                        cycles-=4;
 183.366 +                        return;
 183.367 +                        case 0xF0: /*F2XM1*/
 183.368 +                        ST(0)=pow(2.0,ST(0))-1.0;
 183.369 +                        cycles-=200;
 183.370 +                        return;
 183.371 +                        case 0xF1: /*FYL2X*/
 183.372 +                        ST(1)=ST(1)*(log(ST(0))/log(2.0));
 183.373 +                        x87_pop();
 183.374 +                        cycles-=250;
 183.375 +                        return;
 183.376 +                        case 0xF2: /*FPTAN*/
 183.377 +//                        pclog("Tan of %f = ",ST(0));
 183.378 +                        ST(0)=tan(ST(0));
 183.379 +//                        pclog("%f\n",ST(0));
 183.380 +                        x87_push(1.0);
 183.381 +                        npxs&=~C2;
 183.382 +                        cycles-=235;
 183.383 +                        return;
 183.384 +                        case 0xF3: /*FPATAN*/
 183.385 +//                        pclog("FPATAN %08X\n",pc);
 183.386 +                        ST(1)=atan2(ST(1),ST(0));
 183.387 +                        x87_pop();
 183.388 +                        cycles-=250;
 183.389 +                        return;
 183.390 +                        case 0xF6: /*FDECSTP*/
 183.391 +                        TOP=(TOP-1)&7;
 183.392 +                        return;
 183.393 +                        case 0xF7: /*FINCSTP*/
 183.394 +                        TOP=(TOP+1)&7;
 183.395 +                        return;
 183.396 +                        case 0xF8: /*FPREM*/
 183.397 +                        temp64=(int64_t)(ST(0)/ST(1));
 183.398 +                        ST(0)=ST(0)-(ST(1)*(double)temp64);
 183.399 +                        npxs&=~(C0|C1|C2|C3);
 183.400 +                        if (temp64&4) npxs|=C0;
 183.401 +                        if (temp64&2) npxs|=C3;
 183.402 +                        if (temp64&1) npxs|=C1;
 183.403 +                        cycles-=100;
 183.404 +                        return;
 183.405 +                        case 0xFA: /*FSQRT*/
 183.406 +                        ST(0)=sqrt(ST(0));
 183.407 +                        cycles-=83;
 183.408 +                        return;
 183.409 +                        case 0xFB: /*FSINCOS*/
 183.410 +                        td=ST(0);
 183.411 +                        ST(0)=sin(td);
 183.412 +                        x87_push(cos(td));
 183.413 +                        npxs&=~C2;
 183.414 +                        cycles-=330;
 183.415 +                        return;
 183.416 +                        case 0xFC: /*FRNDINT*/
 183.417 +//                        pclog("FRNDINT %f %i ",ST(0),(npxc>>10)&3);
 183.418 +                        ST(0)=(double)x87_fround(ST(0));
 183.419 +//                        pclog("%f\n",ST(0));
 183.420 +                        cycles-=21;
 183.421 +                        return;
 183.422 +                        case 0xFD: /*FSCALE*/
 183.423 +                        temp64=(int64_t)ST(1);
 183.424 +                        ST(0)=ST(0)*pow(2.0,(double)temp64);
 183.425 +                        cycles-=30;
 183.426 +                        return;
 183.427 +                        case 0xFE: /*FSIN*/
 183.428 +                        ST(0)=sin(ST(0));
 183.429 +                        npxs&=~C2;
 183.430 +                        cycles-=300;
 183.431 +                        return;
 183.432 +                        case 0xFF: /*FCOS*/
 183.433 +                        ST(0)=cos(ST(0));
 183.434 +                        npxs&=~C2;
 183.435 +                        cycles-=300;
 183.436 +                        return;
 183.437 +                }
 183.438 +        }
 183.439 +        else
 183.440 +        {
 183.441 +                switch (reg)
 183.442 +                {
 183.443 +                        case 0: /*FLD single-precision*/
 183.444 +//                        if ((rmdat32&0xFFFF)==0xD445) { pclog("FLDS\n"); output=3; dumpregs(); exit(-1); }
 183.445 +                        ts.i=(float)geteal(); if (abrt) return;
 183.446 +                        x87_push((double)ts.s);
 183.447 +                        cycles-=3;
 183.448 +                        return;
 183.449 +                        case 2: /*FST single-precision*/
 183.450 +                        ts.s=(float)ST(0);
 183.451 +                        seteal(ts.i);
 183.452 +                        cycles-=7;
 183.453 +                        return;
 183.454 +                        case 3: /*FSTP single-precision*/
 183.455 +                        ts.s=(float)ST(0);
 183.456 +                        seteal(ts.i); if (abrt) return;
 183.457 +  //                      if (pc==0x3f50c) pclog("FSTP %f %f %08X\n",ST(0),ts.s,ts.i);
 183.458 +                        x87_pop();
 183.459 +                        cycles-=7;
 183.460 +                        return;
 183.461 +                        case 4: /*FLDENV*/
 183.462 +                        switch ((cr0&1)|(op32&0x100))
 183.463 +                        {
 183.464 +                                case 0x000: /*16-bit real mode*/
 183.465 +                                case 0x001: /*16-bit protected mode*/
 183.466 +                                npxc=readmemw(easeg,eaaddr);
 183.467 +                                npxs=readmemw(easeg,eaaddr+2);
 183.468 +                                tag=readmemw(easeg,eaaddr+4);
 183.469 +                                TOP=(npxs>>11)&7;
 183.470 +                                break;
 183.471 +                                case 0x100: /*32-bit real mode*/
 183.472 +                                case 0x101: /*32-bit protected mode*/
 183.473 +                                npxc=readmemw(easeg,eaaddr);
 183.474 +                                npxs=readmemw(easeg,eaaddr+4);
 183.475 +                                tag=readmemw(easeg,eaaddr+8);
 183.476 +                                TOP=(npxs>>11)&7;
 183.477 +                                break;
 183.478 +                        }
 183.479 +                        cycles-=(cr0&1)?34:44;
 183.480 +                        return;
 183.481 +                        case 5: /*FLDCW*/
 183.482 +                        tempw=geteaw();
 183.483 +                        if (abrt) return;
 183.484 +                        npxc=tempw;
 183.485 +                        cycles-=4;
 183.486 +                        return;
 183.487 +                        case 6: /*FSTENV*/
 183.488 +                        switch ((cr0&1)|(op32&0x100))
 183.489 +                        {
 183.490 +                                case 0x000: /*16-bit real mode*/
 183.491 +                                writememw(easeg,eaaddr,npxc);
 183.492 +                                writememw(easeg,eaaddr+2,npxs);
 183.493 +                                writememw(easeg,eaaddr+4,tag);
 183.494 +                                writememw(easeg,eaaddr+6,x87_pc_off);
 183.495 +                                writememw(easeg,eaaddr+10,x87_op_off);
 183.496 +                                break;
 183.497 +                                case 0x001: /*16-bit protected mode*/
 183.498 +                                writememw(easeg,eaaddr,npxc);
 183.499 +                                writememw(easeg,eaaddr+2,npxs);
 183.500 +                                writememw(easeg,eaaddr+4,tag);
 183.501 +                                writememw(easeg,eaaddr+6,x87_pc_off);
 183.502 +                                writememw(easeg,eaaddr+8,x87_pc_seg);
 183.503 +                                writememw(easeg,eaaddr+10,x87_op_off);
 183.504 +                                writememw(easeg,eaaddr+12,x87_op_seg);
 183.505 +                                break;
 183.506 +                                case 0x100: /*32-bit real mode*/
 183.507 +                                writememw(easeg,eaaddr,npxc);
 183.508 +                                writememw(easeg,eaaddr+4,npxs);
 183.509 +                                writememw(easeg,eaaddr+8,tag);
 183.510 +                                writememw(easeg,eaaddr+12,x87_pc_off);
 183.511 +                                writememw(easeg,eaaddr+20,x87_op_off);
 183.512 +                                writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12);
 183.513 +                                break;
 183.514 +                                case 0x101: /*32-bit protected mode*/
 183.515 +                                writememw(easeg,eaaddr,npxc);
 183.516 +                                writememw(easeg,eaaddr+4,npxs);
 183.517 +                                writememw(easeg,eaaddr+8,tag);
 183.518 +                                writememl(easeg,eaaddr+12,x87_pc_off);
 183.519 +                                writememl(easeg,eaaddr+16,x87_pc_seg);
 183.520 +                                writememl(easeg,eaaddr+20,x87_op_off);
 183.521 +                                writememl(easeg,eaaddr+24,x87_op_seg);
 183.522 +                                break;
 183.523 +                        }
 183.524 +                        cycles-=(cr0&1)?56:67;
 183.525 +                        return;
 183.526 +                        case 7: /*FSTCW*/
 183.527 +                        seteaw(npxc);
 183.528 +                        cycles-=3;
 183.529 +                        return;
 183.530 +                }
 183.531 +        }
 183.532 +//        fatal("Bad x87 D9 opcode %i %02X\n",reg,rmdat32&0xFF);
 183.533 +        x86illegal();
 183.534 +}
 183.535 +void x87_da()
 183.536 +{
 183.537 +        int32_t templ;
 183.538 +        if (mod==3)
 183.539 +        {
 183.540 +                switch (rmdat32&0xFF)
 183.541 +                {
 183.542 +                        case 0xE9: /*FUCOMPP*/
 183.543 +                        npxs&=~(C0|C2|C3);
 183.544 +                        if (ST(0)==ST(1))     npxs|=C3;
 183.545 +                        else if (ST(0)<ST(1)) npxs|=C0;
 183.546 +                        x87_pop();
 183.547 +                        x87_pop();
 183.548 +                        cycles-=5;
 183.549 +                        return;
 183.550 +                }
 183.551 +        }
 183.552 +        else
 183.553 +        {
 183.554 +                templ=geteal(); if (abrt) return;
 183.555 +                switch (reg)
 183.556 +                {
 183.557 +                        case 0: /*FIADD*/
 183.558 +                        ST(0)=ST(0)+(double)templ;
 183.559 +                        cycles-=20;
 183.560 +                        return;
 183.561 +                        case 1: /*FIMUL*/
 183.562 +                        ST(0)=ST(0)*(double)templ;
 183.563 +                        cycles-=22;
 183.564 +                        return;
 183.565 +                        case 2: /*FICOM*/
 183.566 +                        npxs&=~(C0|C2|C3);
 183.567 +                        if (ST(0)==(double)templ)     npxs|=C3;
 183.568 +                        else if (ST(0)<(double)templ) npxs|=C0;
 183.569 +                        cycles-=15;
 183.570 +                        return;
 183.571 +                        case 3: /*FICOMP*/
 183.572 +                        npxs&=~(C0|C2|C3);
 183.573 +                        if (ST(0)==(double)templ)     npxs|=C3;
 183.574 +                        else if (ST(0)<(double)templ) npxs|=C0;
 183.575 +                        x87_pop();
 183.576 +                        cycles-=15;
 183.577 +                        return;
 183.578 +                        case 4: /*FISUB*/
 183.579 +                        ST(0)=ST(0)-(double)templ;
 183.580 +                        cycles-=20;
 183.581 +                        return;
 183.582 +                        case 5: /*FISUBR*/
 183.583 +                        ST(0)=(double)templ-ST(0);
 183.584 +                        cycles-=19;
 183.585 +                        return;
 183.586 +                        case 6: /*FIDIV*/
 183.587 +                        ST(0)=ST(0)/(double)templ;
 183.588 +                        cycles-=84;
 183.589 +                        return;
 183.590 +                        case 7: /*FIDIVR*/
 183.591 +                        ST(0)=(double)templ/ST(0);
 183.592 +                        cycles-=84;
 183.593 +                        return;
 183.594 +                }
 183.595 +        }
 183.596 +//        fatal("Bad x87 DA opcode %i %02X\n",reg,rmdat32&0xFF);
 183.597 +        x86illegal();
 183.598 +}
 183.599 +void x87_db()
 183.600 +{
 183.601 +        double t;
 183.602 +        int32_t templ;
 183.603 +        if (mod==3)
 183.604 +        {
 183.605 +                switch (reg)
 183.606 +                {
 183.607 +                        case 4:
 183.608 +                        switch (rmdat32&0xFF)
 183.609 +                        {
 183.610 +                                case 0xE1:
 183.611 +                                return;
 183.612 +                                case 0xE2: /*FCLEX*/
 183.613 +                                npxs&=0xFF00;
 183.614 +                                return;
 183.615 +                                case 0xE3: /*FINIT*/
 183.616 +                                npxc=0x37F;
 183.617 +                                npxs=0;
 183.618 +                                tag=0xFFFF;
 183.619 +                                TOP=0;
 183.620 +                                cycles-=17;
 183.621 +                                return;
 183.622 +                                case 0xE4:
 183.623 +                                return;
 183.624 +                        }
 183.625 +                        break;
 183.626 +                }
 183.627 +        }
 183.628 +        else
 183.629 +        {
 183.630 +                switch (reg)
 183.631 +                {
 183.632 +                        case 0: /*FILD short*/
 183.633 +                        templ=geteal(); if (abrt) return;
 183.634 +                        x87_push((double)templ);
 183.635 +                        cycles-=9;
 183.636 +                        return;
 183.637 +                        case 2: /*FIST short*/
 183.638 +                        seteal((int32_t)x87_fround(ST(0)));
 183.639 +                        cycles-=28;
 183.640 +                        return;
 183.641 +                        case 3: /*FISTP short*/
 183.642 +                        seteal((int32_t)x87_fround(ST(0))); if (abrt) return;
 183.643 +                        x87_pop();
 183.644 +                        cycles-=28;
 183.645 +                        return;
 183.646 +                        case 5: /*FLD extended*/
 183.647 +                        t=x87_ld80(); if (abrt) return;
 183.648 +                        x87_push(t);
 183.649 +                        cycles-=6;
 183.650 +                        return;
 183.651 +                        case 7: /*FSTP extended*/
 183.652 +                        x87_st80(ST(0)); if (abrt) return;
 183.653 +                        x87_pop();
 183.654 +                        cycles-=6;
 183.655 +                        return;
 183.656 +                }
 183.657 +        }
 183.658 +//        fatal("Bad x87 DB opcode %i %02X\n",reg,rmdat32&0xFF);
 183.659 +        x86illegal();
 183.660 +}
 183.661 +void x87_dc()
 183.662 +{
 183.663 +        union
 183.664 +        {
 183.665 +                double d;
 183.666 +                uint64_t i;
 183.667 +        } t;
 183.668 +        if (mod==3)
 183.669 +        {
 183.670 +                switch (rmdat32&0xFF)
 183.671 +                {
 183.672 +                        case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADD*/
 183.673 +                        case 0xC4: case 0xC5: case 0xC6: case 0xC7:
 183.674 +                        ST(rmdat32&7)=ST(rmdat32&7)+ST(0);
 183.675 +                        cycles-=8;
 183.676 +                        return;
 183.677 +                        case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMUL*/
 183.678 +                        case 0xCC: case 0xCD: case 0xCE: case 0xCF:
 183.679 +                        ST(rmdat32&7)=ST(rmdat32&7)*ST(0);
 183.680 +                        cycles-=16;
 183.681 +                        return;
 183.682 +                        case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBR*/
 183.683 +                        case 0xE4: case 0xE5: case 0xE6: case 0xE7:
 183.684 +                        ST(rmdat32&7)=ST(0)-ST(rmdat32&7);
 183.685 +                        cycles-=8;
 183.686 +                        return;
 183.687 +                        case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUB*/
 183.688 +                        case 0xEC: case 0xED: case 0xEE: case 0xEF:
 183.689 +                        ST(rmdat32&7)=ST(rmdat32&7)-ST(0);
 183.690 +                        cycles-=8;
 183.691 +                        return;
 183.692 +                        case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVR*/
 183.693 +                        case 0xF4: case 0xF5: case 0xF6: case 0xF7:
 183.694 +                        ST(rmdat32&7)=ST(0)/ST(rmdat32&7);
 183.695 +                        cycles-=73;
 183.696 +                        return;
 183.697 +                        case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIV*/
 183.698 +                        case 0xFC: case 0xFD: case 0xFE: case 0xFF:
 183.699 +                        ST(rmdat32&7)=ST(rmdat32&7)/ST(0);
 183.700 +                        cycles-=73;
 183.701 +                        return;
 183.702 +                }
 183.703 +        }
 183.704 +        else
 183.705 +        {
 183.706 +                t.i=readmeml(easeg,eaaddr);
 183.707 +                t.i|=(uint64_t)readmeml(easeg,eaaddr+4)<<32;
 183.708 +                if (abrt) return;
 183.709 +                switch (reg)
 183.710 +                {
 183.711 +                        case 0: /*FADD double*/
 183.712 +                        ST(0)+=t.d;
 183.713 +                        cycles-=8;
 183.714 +                        return;
 183.715 +                        case 1: /*FMUL double*/
 183.716 +                        ST(0)*=t.d;
 183.717 +                        cycles-=14;
 183.718 +                        return;
 183.719 +                        case 2: /*FCOM double*/
 183.720 +                        npxs&=~(C0|C2|C3);
 183.721 +                        if (ST(0)==t.d)     npxs|=C3;
 183.722 +                        else if (ST(0)<t.d) npxs|=C0;
 183.723 +                        cycles-=4;
 183.724 +                        return;
 183.725 +                        case 3: /*FCOMP double*/
 183.726 +                        npxs&=~(C0|C2|C3);
 183.727 +                        if (ST(0)==t.d)     npxs|=C3;
 183.728 +                        else if (ST(0)<t.d) npxs|=C0;
 183.729 +                        cycles-=4;
 183.730 +                        x87_pop();
 183.731 +                        return;
 183.732 +                        case 4: /*FSUB double*/
 183.733 +                        ST(0)-=t.d;
 183.734 +                        cycles-=8;
 183.735 +                        return;
 183.736 +                        case 5: /*FSUBR double*/
 183.737 +                        ST(0)=t.d-ST(0);
 183.738 +                        cycles-=8;
 183.739 +                        return;
 183.740 +                        case 6: /*FDIV double*/
 183.741 +                        ST(0)=ST(0)/t.d;
 183.742 +                        cycles-=73;
 183.743 +                        return;
 183.744 +                        case 7: /*FDIVR double*/
 183.745 +                        ST(0)=t.d/ST(0);
 183.746 +                        cycles-=73;
 183.747 +                        return;
 183.748 +                }
 183.749 +        }
 183.750 +//        fatal("Bad x87 DC opcode %i %02X\n",reg,rmdat32&0xFF);
 183.751 +        x86illegal();
 183.752 +}
 183.753 +void x87_dd()
 183.754 +{
 183.755 +        union
 183.756 +        {
 183.757 +                double d;
 183.758 +                uint64_t i;
 183.759 +        } t;
 183.760 +        int temp;
 183.761 +        if (mod==3)
 183.762 +        {
 183.763 +                switch (reg)
 183.764 +                {
 183.765 +                        case 0: /*FFREE*/
 183.766 +                        tag|=(3<<((rmdat32&7)<<1));
 183.767 +                        cycles-=3;
 183.768 +                        return;
 183.769 +                        case 2: /*FST*/
 183.770 +                        ST(rmdat32&7)=ST(0);
 183.771 +                        temp=(tag>>((TOP&7)<<1))&3;
 183.772 +                        tag&=~(3<<((rmdat32&7)<<1));
 183.773 +                        tag|=(temp<<((rmdat32&7)<<1));
 183.774 +                        cycles-=3;
 183.775 +                        return;
 183.776 +                        case 3: /*FSTP*/
 183.777 +                        ST(rmdat32&7)=ST(0);
 183.778 +                        temp=(tag>>((TOP&7)<<1))&3;
 183.779 +                        tag&=~(3<<((rmdat32&7)<<1));
 183.780 +                        tag|=(temp<<((rmdat32&7)<<1));
 183.781 +                        x87_pop();
 183.782 +                        cycles-=3;
 183.783 +                        return;
 183.784 +                        case 4: /*FUCOM*/
 183.785 +                        npxs&=~(C0|C2|C3);
 183.786 +                        if (ST(0)==ST(rmdat32&7))     npxs|=C3;
 183.787 +                        else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
 183.788 +                        cycles-=4;
 183.789 +                        return;
 183.790 +                        case 5: /*FUCOMP*/
 183.791 +                        npxs&=~(C0|C2|C3);
 183.792 +                        if (ST(0)==ST(rmdat32&7))     npxs|=C3;
 183.793 +                        else if (ST(0)<ST(rmdat32&7)) npxs|=C0;
 183.794 +                        x87_pop();
 183.795 +                        cycles-=4;
 183.796 +                        return;
 183.797 +                }
 183.798 +        }
 183.799 +        else
 183.800 +        {
 183.801 +                switch (reg)
 183.802 +                {
 183.803 +                        case 0: /*FLD double-precision*/
 183.804 +                        t.i=readmeml(easeg,eaaddr);
 183.805 +                        t.i|=(uint64_t)readmeml(easeg,eaaddr+4)<<32; if (abrt) return;
 183.806 +                        x87_push(t.d);
 183.807 +                        cycles-=3;
 183.808 +                        return;
 183.809 +                        case 2: /*FST double-precision*/
 183.810 +                        t.d=ST(0);
 183.811 +                        writememl(easeg,eaaddr,t.i);
 183.812 +                        writememl(easeg,eaaddr+4,(t.i>>32));
 183.813 +                        cycles-=8;
 183.814 +                        return;
 183.815 +                        case 3: /*FSTP double-precision*/
 183.816 +                        t.d=ST(0);
 183.817 +                        writememl(easeg,eaaddr,t.i);
 183.818 +                        writememl(easeg,eaaddr+4,(t.i>>32)); if (abrt) return;
 183.819 +                        x87_pop();
 183.820 +                        cycles-=8;
 183.821 +                        return;
 183.822 +                        case 4: /*FRSTOR*/
 183.823 +                        switch ((cr0&1)|(op32&0x100))
 183.824 +                        {
 183.825 +                                case 0x000: /*16-bit real mode*/
 183.826 +                                case 0x001: /*16-bit protected mode*/
 183.827 +                                npxc=readmemw(easeg,eaaddr);
 183.828 +                                npxs=readmemw(easeg,eaaddr+2);
 183.829 +                                tag=readmemw(easeg,eaaddr+4);
 183.830 +                                TOP=(npxs>>11)&7;
 183.831 +                                eaaddr+=14;
 183.832 +                                break;
 183.833 +                                case 0x100: /*32-bit real mode*/
 183.834 +                                case 0x101: /*32-bit protected mode*/
 183.835 +                                npxc=readmemw(easeg,eaaddr);
 183.836 +                                npxs=readmemw(easeg,eaaddr+4);
 183.837 +                                tag=readmemw(easeg,eaaddr+8);
 183.838 +                                TOP=(npxs>>11)&7;
 183.839 +                                eaaddr+=28;
 183.840 +                                break;
 183.841 +                        }
 183.842 +                        ST(0)=x87_ld80(); eaaddr+=10;
 183.843 +                        ST(1)=x87_ld80(); eaaddr+=10;
 183.844 +                        ST(2)=x87_ld80(); eaaddr+=10;
 183.845 +                        ST(3)=x87_ld80(); eaaddr+=10;
 183.846 +                        ST(4)=x87_ld80(); eaaddr+=10;
 183.847 +                        ST(5)=x87_ld80(); eaaddr+=10;
 183.848 +                        ST(6)=x87_ld80(); eaaddr+=10;
 183.849 +                        ST(7)=x87_ld80();
 183.850 +                        cycles-=(cr0&1)?34:44;
 183.851 +                        return;
 183.852 +                        case 6: /*FSAVE*/
 183.853 +                        switch ((cr0&1)|(op32&0x100))
 183.854 +                        {
 183.855 +                                case 0x000: /*16-bit real mode*/
 183.856 +                                writememw(easeg,eaaddr,npxc);
 183.857 +                                writememw(easeg,eaaddr+2,npxs);
 183.858 +                                writememw(easeg,eaaddr+4,tag);
 183.859 +                                writememw(easeg,eaaddr+6,x87_pc_off);
 183.860 +                                writememw(easeg,eaaddr+10,x87_op_off);
 183.861 +                                eaaddr+=14;
 183.862 +                                x87_st80(ST(0)); eaaddr+=10;
 183.863 +                                x87_st80(ST(1)); eaaddr+=10;
 183.864 +                                x87_st80(ST(2)); eaaddr+=10;
 183.865 +                                x87_st80(ST(3)); eaaddr+=10;
 183.866 +                                x87_st80(ST(4)); eaaddr+=10;
 183.867 +                                x87_st80(ST(5)); eaaddr+=10;
 183.868 +                                x87_st80(ST(6)); eaaddr+=10;
 183.869 +                                x87_st80(ST(7));
 183.870 +                                break;
 183.871 +                                case 0x001: /*16-bit protected mode*/
 183.872 +                                writememw(easeg,eaaddr,npxc);
 183.873 +                                writememw(easeg,eaaddr+2,npxs);
 183.874 +                                writememw(easeg,eaaddr+4,tag);
 183.875 +                                writememw(easeg,eaaddr+6,x87_pc_off);
 183.876 +                                writememw(easeg,eaaddr+8,x87_pc_seg);
 183.877 +                                writememw(easeg,eaaddr+10,x87_op_off);
 183.878 +                                writememw(easeg,eaaddr+12,x87_op_seg);
 183.879 +                                eaaddr+=14;
 183.880 +                                x87_st80(ST(0)); eaaddr+=10;
 183.881 +                                x87_st80(ST(1)); eaaddr+=10;
 183.882 +                                x87_st80(ST(2)); eaaddr+=10;
 183.883 +                                x87_st80(ST(3)); eaaddr+=10;
 183.884 +                                x87_st80(ST(4)); eaaddr+=10;
 183.885 +                                x87_st80(ST(5)); eaaddr+=10;
 183.886 +                                x87_st80(ST(6)); eaaddr+=10;
 183.887 +                                x87_st80(ST(7));
 183.888 +                                break;
 183.889 +                                case 0x100: /*32-bit real mode*/
 183.890 +                                writememw(easeg,eaaddr,npxc);
 183.891 +                                writememw(easeg,eaaddr+4,npxs);
 183.892 +                                writememw(easeg,eaaddr+8,tag);
 183.893 +                                writememw(easeg,eaaddr+12,x87_pc_off);
 183.894 +                                writememw(easeg,eaaddr+20,x87_op_off);
 183.895 +                                writememl(easeg,eaaddr+24,(x87_op_off>>16)<<12);
 183.896 +                                eaaddr+=28;
 183.897 +                                x87_st80(ST(0)); eaaddr+=10;
 183.898 +                                x87_st80(ST(1)); eaaddr+=10;
 183.899 +                                x87_st80(ST(2)); eaaddr+=10;
 183.900 +                                x87_st80(ST(3)); eaaddr+=10;
 183.901 +                                x87_st80(ST(4)); eaaddr+=10;
 183.902 +                                x87_st80(ST(5)); eaaddr+=10;
 183.903 +                                x87_st80(ST(6)); eaaddr+=10;
 183.904 +                                x87_st80(ST(7));
 183.905 +                                break;
 183.906 +                                case 0x101: /*32-bit protected mode*/
 183.907 +                                writememw(easeg,eaaddr,npxc);
 183.908 +                                writememw(easeg,eaaddr+4,npxs);
 183.909 +                                writememw(easeg,eaaddr+8,tag);
 183.910 +                                writememl(easeg,eaaddr+12,x87_pc_off);
 183.911 +                                writememl(easeg,eaaddr+16,x87_pc_seg);
 183.912 +                                writememl(easeg,eaaddr+20,x87_op_off);
 183.913 +                                writememl(easeg,eaaddr+24,x87_op_seg);
 183.914 +                                eaaddr+=28;
 183.915 +                                x87_st80(ST(0)); eaaddr+=10;
 183.916 +                                x87_st80(ST(1)); eaaddr+=10;
 183.917 +                                x87_st80(ST(2)); eaaddr+=10;
 183.918 +                                x87_st80(ST(3)); eaaddr+=10;
 183.919 +                                x87_st80(ST(4)); eaaddr+=10;
 183.920 +                                x87_st80(ST(5)); eaaddr+=10;
 183.921 +                                x87_st80(ST(6)); eaaddr+=10;
 183.922 +                                x87_st80(ST(7));
 183.923 +                                break;
 183.924 +                        }
 183.925 +                        cycles-=(cr0&1)?56:67;
 183.926 +                        return;
 183.927 +                        case 7: /*FSTSW*/
 183.928 +                        seteaw((npxs&0xC7FF)|(TOP<<11));
 183.929 +                        cycles-=3;
 183.930 +                        return;
 183.931 +                }
 183.932 +        }
 183.933 +//        fatal("Bad x87 DD opcode %i %02X\n",reg,rmdat32&0xFF);
 183.934 +        x86illegal();
 183.935 +}
 183.936 +void x87_de()
 183.937 +{
 183.938 +        double t;
 183.939 +        int32_t templ;
 183.940 +        if (mod==3)
 183.941 +        {
 183.942 +                switch (rmdat32&0xFF)
 183.943 +                {
 183.944 +                        case 0xC0: case 0xC1: case 0xC2: case 0xC3: /*FADDP*/
 183.945 +                        case 0xC4: case 0xC5: case 0xC6: case 0xC7:
 183.946 +                        ST(rmdat32&7)=ST(rmdat32&7)+ST[TOP];
 183.947 +                        x87_pop();
 183.948 +                        cycles-=8;
 183.949 +                        return;
 183.950 +                        case 0xC8: case 0xC9: case 0xCA: case 0xCB: /*FMULP*/
 183.951 +                        case 0xCC: case 0xCD: case 0xCE: case 0xCF:
 183.952 +                        ST(rmdat32&7)=ST(rmdat32&7)*ST[TOP];
 183.953 +                        x87_pop();
 183.954 +                        cycles-=16;
 183.955 +                        return;
 183.956 +                        case 0xD9: /*FCOMPP*/
 183.957 +                        npxs&=~(C0|C2|C3);
 183.958 +                        if (ST(0)==ST(1))     npxs|=C3;
 183.959 +                        else if (ST(0)<ST(1)) npxs|=C0;
 183.960 +                        x87_pop();
 183.961 +                        x87_pop();
 183.962 +                        cycles-=5;
 183.963 +                        return;
 183.964 +                        case 0xE0: case 0xE1: case 0xE2: case 0xE3: /*FSUBRP*/
 183.965 +                        case 0xE4: case 0xE5: case 0xE6: case 0xE7:
 183.966 +                        ST(rmdat32&7)=ST(0)-ST(rmdat32&7);
 183.967 +                        x87_pop();
 183.968 +                        cycles-=8;
 183.969 +                        return;
 183.970 +                        case 0xE8: case 0xE9: case 0xEA: case 0xEB: /*FSUBP*/
 183.971 +                        case 0xEC: case 0xED: case 0xEE: case 0xEF:
 183.972 +                        ST(rmdat32&7)=ST(rmdat32&7)-ST[TOP];
 183.973 +                        x87_pop();
 183.974 +                        cycles-=8;
 183.975 +                        return;
 183.976 +                        case 0xF0: case 0xF1: case 0xF2: case 0xF3: /*FDIVRP*/
 183.977 +                        case 0xF4: case 0xF5: case 0xF6: case 0xF7:
 183.978 +                        ST(rmdat32&7)=ST(0)/ST(rmdat32&7);
 183.979 +                        x87_pop();
 183.980 +                        cycles-=73;
 183.981 +                        return;
 183.982 +                        case 0xF8: case 0xF9: case 0xFA: case 0xFB: /*FDIVP*/
 183.983 +                        case 0xFC: case 0xFD: case 0xFE: case 0xFF:
 183.984 +                        ST(rmdat32&7)=ST(rmdat32&7)/ST[TOP];
 183.985 +                        x87_pop();
 183.986 +                        cycles-=73;
 183.987 +                        return;
 183.988 +                }
 183.989 +        }
 183.990 +        else
 183.991 +        {
 183.992 +                templ=(int32_t)geteaw(); if (abrt) return;
 183.993 +                switch (reg)
 183.994 +                {
 183.995 +                        case 0: /*FIADD*/
 183.996 +                        ST(0)=ST(0)+(double)templ;
 183.997 +                        cycles-=20;
 183.998 +                        return;
 183.999 +                        case 1: /*FIMUL*/
183.1000 +                        ST(0)=ST(0)*(double)templ;
183.1001 +                        cycles-=22;
183.1002 +                        return;
183.1003 +                        case 2: /*FICOM*/
183.1004 +                        npxs&=~(C0|C2|C3);
183.1005 +                        if (ST(0)==(double)templ)     npxs|=C3;
183.1006 +                        else if (ST(0)<(double)templ) npxs|=C0;
183.1007 +                        cycles-=15;
183.1008 +                        return;
183.1009 +                        case 3: /*FICOMP*/
183.1010 +                        npxs&=~(C0|C2|C3);
183.1011 +                        if (ST(0)==(double)templ)     npxs|=C3;
183.1012 +                        else if (ST(0)<(double)templ) npxs|=C0;
183.1013 +                        x87_pop();
183.1014 +                        cycles-=15;
183.1015 +                        return;
183.1016 +                        case 4: /*FISUB*/
183.1017 +                        ST(0)=ST(0)-(double)templ;
183.1018 +                        cycles-=20;
183.1019 +                        return;
183.1020 +                        case 5: /*FISUBR*/
183.1021 +                        ST(0)=(double)templ-ST(0);
183.1022 +                        cycles-=19;
183.1023 +                        return;
183.1024 +                        case 6: /*FIDIV*/
183.1025 +                        ST(0)=ST(0)/(double)templ;
183.1026 +                        cycles-=84;
183.1027 +                        return;
183.1028 +                        case 7: /*FIDIVR*/
183.1029 +                        ST(0)=(double)templ/ST(0);
183.1030 +                        cycles-=84;
183.1031 +                        return;
183.1032 +                }
183.1033 +        }
183.1034 +//        fatal("Bad x87 DE opcode %i %02X\n",reg,rmdat32&0xFF);
183.1035 +        x86illegal();
183.1036 +}
183.1037 +void x87_df()
183.1038 +{
183.1039 +        int c;
183.1040 +        int64_t temp64;
183.1041 +        int16_t temp16;
183.1042 +        double tempd;
183.1043 +        uint8_t tempc;
183.1044 +        if (mod==3)
183.1045 +        {
183.1046 +                switch (reg)
183.1047 +                {
183.1048 +                        case 4:
183.1049 +                        switch (rmdat32&0xFF)
183.1050 +                        {
183.1051 +                                case 0xE0: /*FSTSW AX*/
183.1052 +                                AX=npxs;
183.1053 +                                cycles-=3;
183.1054 +                                return;
183.1055 +                        }
183.1056 +                        break;
183.1057 +                }
183.1058 +        }
183.1059 +        else
183.1060 +        {
183.1061 +                switch (reg)
183.1062 +                {
183.1063 +                        case 0: /*FILD short*/
183.1064 +                        temp16=geteaw(); if (abrt) return;
183.1065 +                        x87_push((double)temp16);
183.1066 +                        cycles-=13;
183.1067 +                        return;
183.1068 +                        case 2: /*FIST word*/
183.1069 +                        temp16=x87_fround(ST(0));
183.1070 +                        seteaw(temp16);
183.1071 +                        cycles-=29;
183.1072 +                        return;
183.1073 +                        case 3: /*FISTP word*/
183.1074 +                        temp16=x87_fround(ST(0));
183.1075 +                        seteaw(temp16); if (abrt) return;
183.1076 +                        x87_pop();
183.1077 +                        cycles-=29;
183.1078 +                        return;
183.1079 +                        case 5: /*FILD long*/
183.1080 +                        temp64=geteal(); if (abrt) return;
183.1081 +                        temp64|=(uint64_t)readmeml(easeg,eaaddr+4)<<32;
183.1082 +                        x87_push((double)temp64);
183.1083 +                        cycles-=10;
183.1084 +                        return;
183.1085 +                        case 6: /*FBSTP*/
183.1086 +                        tempd=ST(0);
183.1087 +                        for (c=0;c<9;c++)
183.1088 +                        {
183.1089 +                                tempc=(uint8_t)floor(fmod(tempd,10.0));       tempd-=floor(fmod(tempd,10.0)); tempd/=10.0;
183.1090 +                                tempc|=((uint8_t)floor(fmod(tempd,10.0)))<<4; tempd-=floor(fmod(tempd,10.0)); tempd/=10.0;
183.1091 +                                writememb(easeg,eaaddr+c,tempc);
183.1092 +                        }
183.1093 +                        tempc=(uint8_t)floor(fmod(tempd,10.0));
183.1094 +                        if (tempd<0.0) tempc|=0x80;
183.1095 +                        writememb(easeg,eaaddr+9,tempc); if (abrt) return;
183.1096 +                        x87_pop();
183.1097 +                        return;
183.1098 +                        case 7: /*FISTP long*/
183.1099 +                        temp64=x87_fround(ST(0));
183.1100 +                        seteal(temp64);
183.1101 +                        writememl(easeg,eaaddr+4,temp64>>32); if (abrt) return;
183.1102 +                        x87_pop();
183.1103 +                        cycles-=29;
183.1104 +                        return;
183.1105 +                }
183.1106 +        }
183.1107 +//        fatal("Bad x87 DF opcode %i %02X\n",reg,rmdat32&0xFF);
183.1108 +        x86illegal();
183.1109 +}
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/src/x87.h	Sun Apr 21 14:54:35 2013 +0100
   184.3 @@ -0,0 +1,3 @@
   184.4 +uint32_t x87_pc_off,x87_op_off;
   184.5 +uint16_t x87_pc_seg,x87_op_seg;
   184.6 +extern uint32_t op32;
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/src/xtide.c	Sun Apr 21 14:54:35 2013 +0100
   185.3 @@ -0,0 +1,55 @@
   185.4 +#include "ibm.h"
   185.5 +#include "xtide.h"
   185.6 +#include "ide.h"
   185.7 +
   185.8 +uint8_t xtide_high;
   185.9 +
  185.10 +void xtide_write(uint16_t port, uint8_t val)
  185.11 +{
  185.12 +        switch (port & 0xf)
  185.13 +        {
  185.14 +                case 0x0:
  185.15 +                writeidew(0, val | (xtide_high << 8));
  185.16 +                return;
  185.17 +                
  185.18 +                case 0x1: case 0x2: case 0x3:
  185.19 +                case 0x4: case 0x5: case 0x6: case 0x7:
  185.20 +                writeide(0, (port  & 0xf) | 0x1f0, val);
  185.21 +                return;
  185.22 +                
  185.23 +                case 0x8:
  185.24 +                xtide_high = val;
  185.25 +                return;
  185.26 +                
  185.27 +                case 0xe:
  185.28 +                writeide(0, 0x3f6, val);
  185.29 +                return;
  185.30 +        }
  185.31 +}
  185.32 +
  185.33 +uint8_t xtide_read(uint16_t port)
  185.34 +{
  185.35 +        uint16_t tempw;
  185.36 +        switch (port & 0xf)
  185.37 +        {
  185.38 +                case 0x0:
  185.39 +                tempw = readidew(0);
  185.40 +                xtide_high = tempw >> 8;
  185.41 +                return tempw & 0xff;
  185.42 +                               
  185.43 +                case 0x1: case 0x2: case 0x3:
  185.44 +                case 0x4: case 0x5: case 0x6: case 0x7:
  185.45 +                return readide(0, (port  & 0xf) | 0x1f0);
  185.46 +                
  185.47 +                case 0x8:
  185.48 +                return xtide_high;
  185.49 +                
  185.50 +                case 0xe:
  185.51 +                return readide(0, 0x3f6);
  185.52 +        }
  185.53 +}
  185.54 +
  185.55 +void xtide_init()
  185.56 +{
  185.57 +        io_sethandler(0x0300, 0x0010, xtide_read, NULL, NULL, xtide_write, NULL, NULL);
  185.58 +}
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/src/xtide.h	Sun Apr 21 14:54:35 2013 +0100
   186.3 @@ -0,0 +1,1 @@
   186.4 +void xtide_init();
   187.1 Binary file win486.nvr has changed